shell script to rename folder by info from file inside - shell

well, I got a set of folders each containing a *.nfo file from XBMC (beside other files such as videos and pictures etc).
I want to rename the folder by strings inside the *.nfo file.
The relevant content of such a *.nfo file:
...
<title>Filmtitle</title>
...
<year>2011</year>
...
<director>Werner Herzog</director>
...
UPDATE: here is an unmodified, original .nfo file from XBMC
movie.nfo
I tried a lot with find exec and grep, but I did not really get anythin usable...
In the example above the folder should have the name "Filmtitel [2011, Werner Herzog]"
Maybe someone can help me out!

Try the following script. It extracts the title, year and director from each file and then renames the directory:
find . -type f -name "*.nfo" -print0 | while IFS= read -r -d $'\0' file
do
title="$(sed 's|.*<title>\(.*\)</title>.*|\1|g' $file)"
year="$(sed 's|.*<year>\(.*\)</year>.*|\1|g' $file)"
director="$(sed 's|.*<director>\(.*\)</director>.*|\1|g' $file)"
dirName="${file%/*}"
newDirName="${dirName%/*}/$title [$year, $director]"
# mv "$dirName" "$newDirName"
echo mv "$dirName" "$newDirName"
done
(Simply uncomment the mv command if you are happy that the commands being printed out are correct.)

Related

Append file name with source folder using the FIND command

I need to strip files out of a number of directories that all have the same file name a.txt. The difference comes from the parent folder so
example1\a.txt
example2\a.txt
...
so I am hoping to run a FIND command that will capture a.txt but not overwrite the file as it moves from folder to folder.
so the output would be
example1_a.txt
example2_a.txt
So from another post the FIND command I want is the following
find . -name "a.txt" -execdir echo cp -v {} /path/to/dest/ \;
So I want to modify in some way to append the source folder to the file. so my guess is to manipulate {} somehow to do it.
Thanks in advance
A one liner might be possible, but you could use this:
#!/bin/bash
targetprefix="targetdir"
find . -name "a.txt" -print0 | while read -r -d '' line
do
path=$(dirname "$line")
newpath=$(echo "${path#./}" | tr '/' '_')
target="$targetprefix/$newpath"
filename=$(basename "$line")
cp -v $line $target/$filename
done
change variable "targetprefix" to be the destination directory you desire.
this find with -print0 and while comes from https://mywiki.wooledge.org/BashFAQ/001
since results from find all start with "./", I use "${path#./}" to remove that prefix.
the tr replaces all subsequent "/" with an underscore. This will take care of sub directories
WARNING: I did not test all "weird" directory and filename formats for proper execution (like carriage returns in filenames!).

Finding files from list and copying them into new directory

I want to find files via the command line terminal for OS X and then copy the files that were found to a new directory. The filenames of the files I want to find are in a listexample.txt file and there are about 5000 file names in there.
The file listexample.txt looks like this:
1111 00001 55553.bmp
1113 11312 24125.bmp
…
I tried around with thing like this:
find /directory -type f "`cat listexample.txt`" -exec cp {} …
but can't get it to run.
I have now this, but it doesn't work:
cat listexample.txt | while read line; do grep "$line" listexample.txt -exec find /directorya "$line" -exec cp {} /directoryb \; done
The idea is to read the lines of list example.txt, then take the line with grep, find the file in directory a and then copy the found file over to a new directory b. I think because of the nature of my file names, see above, there is a problem with spaces in the name as well.
I also started this approach to see what is going on, but didn't get far.
for line in `cat listexample.txt`; do grep $line -exec echo "Processing $line"; done
Here's the solution for a find and copy script (copy.sh) in case somebody has a similar problem:
First, give rights to the script with: chmod +x fcopy.sh
Then run it with: ./fcopy.sh listexample.txt
Script content:
#!/bin/bash
target="/directory with images"
while read line
do
name=$line
echo "Text read from file - $name"
find "${target}" -name "$name" -exec cp {} /found_files \;
done < $1
Cheers

Move files to directories based on some part of file name?

I have several thousand eBooks named like AuthorFirstName AuthorLastName Title XX.pdf, where xx are number from 1-99 (volume number).
Author tilte name can be of multiple word so here i want to move copy the files to folder with the name AuthorFirstName AuthorLastName title. Everything except the number should be the folder name, so that all volumes of the eBook come in same folder.
For example
root.....>AuthorFirstName AuthorLastName Title>AuthorFirstName AuthorLastName Title XX.pdf
You can use a mix of find, sed and bash script for the task. You have to write it on your own though and ask for help if you fail.
You can also try some ready tools for mass moving/renaming like these: http://tldp.org/LDP/GNU-Linux-Tools-Summary/html/mass-rename.html
Never used one of these though.
I would try with this:
for folder in $(ls | sed -r "s/(.*) ([0-9]{1,2})/\1/" | uniq)
do
mkdir $folder
mv $(find . -name "$folder*") $folder
done
I don't know if this is correct, but it may give you some hints.
edit: added uniq to the pipe.
Use a loop as shown below:
find . -type f -name "*pdf" -print0 | while IFS= read -d '' file
do
# extract the name of the directory to create
dirName="${file% *}"
# create the directory if it doesn't exist
[[ ! -d "$dirName" ]] && mkdir "$dirName"
mv "$file" "$dirName"
done

How to copy and rename files in shell script

I have a folder "test" in it there is 20 other folder with different names like A,B ....(actually they are name of people not A, B...) I want to write a shell script that go to each folder like test/A and rename all the .c files with A[1,2..] and copy them to "test" folder. I started like this but I have no idea how to complete it!
#!/bin/sh
for file in `find test/* -name '*.c'`; do mv $file $*; done
Can you help me please?
This code should get you close. I tried to document exactly what I was doing.
It does rely on BASH and the GNU version of find to handle spaces in file names. I tested it on a directory fill of .DOC files, so you'll want to change the extension as well.
#!/bin/bash
V=1
SRC="."
DEST="/tmp"
#The last path we saw -- make it garbage, but not blank. (Or it will break the '[' test command
LPATH="/////"
#Let us find the files we want
find $SRC -iname "*.doc" -print0 | while read -d $'\0' i
do
echo "We found the file name... $i";
#Now, we rip off the off just the file name.
FNAME=$(basename "$i" .doc)
echo "And the basename is $FNAME";
#Now we get the last chunk of the directory
ZPATH=$(dirname "$i" | awk -F'/' '{ print $NF}' )
echo "And the last chunk of the path is... $ZPATH"
# If we are down a new path, then reset our counter.
if [ $LPATH == $ZPATH ]; then
V=1
fi;
LPATH=$ZPATH
# Eat the error message
mkdir $DEST/$ZPATH 2> /dev/null
echo cp \"$i\" \"$DEST/${ZPATH}/${FNAME}${V}\"
cp "$i" "$DEST/${ZPATH}/${FNAME}${V}"
done
#!/bin/bash
## Find folders under test. This assumes you are already where test exists OR give PATH before "test"
folders="$(find test -maxdepth 1 -type d)"
## Look into each folder in $folders and find folder[0-9]*.c file n move them to test folder, right?
for folder in $folders;
do
##Find folder-named-.c files.
leaf_folder="${folder##*/}"
folder_named_c_files="$(find $folder -type f -name "*.c" | grep "${leaf_folder}[0-9]")"
## Move these folder_named_c_files to test folder. basename will hold just the file name.
## Don't know as you didn't mention what name the file to rename to, so tweak mv command acc..
for file in $folder_named_c_files; do basename=$file; mv $file test/$basename; done
done

basic shell script

I have some video files all ending in .wmv .mov .mpg. I have music files ending in .mp3 .wma. And finally I have some text files all end in the extension .txt
I wrote a shell script that generates subfolders, one for the music files, one for the video files, and one for the text files, and then organizes all of the files into the correct subfolders.
But I ran into a little problem ...
*** I would like the script to be interactive and to prompt the user if he/she wants to organize the files. Also, I would like the script to write a log file that contains, for each file, the original file name, as well as the new file path/name it was moved to. And I would like the script to accept a command line argument, which is the folder that contains the unorganized files. This should allow the script to be located and run from anywhere in the file system, and accept any folder of unorganized files.
Example:
organizefiles.sh mystuff/media
where the subfolders would go inside "media"
Any ideas on how to do that?
Thank you!
here's a partial implementation for you to start with. Try and do the rest yourself.
find /path -type f \( -iname "*.mp3" -o -iname "*.txt" \) -exec file -N "{}" + | while IFS=":" read -r filename type
do
case "$type" in
*[vV]ideo*|*AVI* ) echo "Video: $filename";;
*[Aa]udio*|*MPEG*ADTS*) echo "Audio file: $filename";;
*[Aa]scii*[tT]ext*) echo "Text: $filename" ;;
* ) echo "No type: $filename-> type: $type";;
esac
done
Please read bash tutorial or this to get familiarize with shell scripting.
I would recommend switching to python, much easier to write and maintain such a code.
As for bash:
Reading input: read
Reading command line arguments: see here
Writing to a log file, simply do echo "something" >> mylogfile.log
Here is the script I have so far
#!/bin/bash
mkdir movies
mkdir songs
mkdir textfiles
mv *.wmv movies
mv *.mov movies
mv *.mpg movies
mv *.mp3 songs
mv *.wma songs
mv *.txt text
ls -l movies, >> log.txt
ls -l songs >> log.txt
ls -l textfiles >> log.txt

Resources