bms9nmh bms9nmh - 4 months ago 8
Linux Question

Adapt file renaming script so that it searches out each file in sub-directories

I have a

.csv
file in which looks something like this:

unnamed_0711-42_p1.mov,day1_0711-42_p1.mov
unnamed_0711-51_p2.mov,day1_0711-51_p2.mov
unnamed_0716-42_p1_2.mov,day1_0716-42_p1_2.mov
unnamed_0716-51_p2_2.mov,day1_0716-51_p2_2.mov


I have written this code to rename files from the name in field 1 (e.g.
unnamed_0711-42_p1.mov
), to the name in field 2 (e.g.
day1_0711-42_p1.mov
).

csv=/location/rename.csv

cat $csv | while IFS=, read -r -a arr; do mv "${arr[@]}"; done


However, this script only works when it and all the files that need to be renamed are in the same directory. This was okay previously, but now I need to find files in various subdirectories (without adding the full path to my
.csv
file).

How can I adapt my script so that is searches out the files in subdirectories then changes the name as before?

Answer

A simple way to make this work, though it leads to an inefficient script, is this:

for D in `find . -type d`
do
    cat $csv | while IFS=, read -r -a arr; do mv "${arr[@]}"; done
done

This will run your command for every directory in the current directory, but this runs through the entire list of filenames for every subdirectory. An alternative would be to search for each file as you process it's name:

csv=files.csv
while IFS=, read -ra arr; do
    find . -name "${arr[0]}" | while IFS= read -r old_file; do
        old_dir=$(dirname "$old_file")
        mv "$old_file" "$old_dir/${arr[1]}"
    done
done<$csv

This uses find to locate each old filename, then uses dirname to get the directory of the old file (which we need so that mv does not place the renamed file into a different directory).

This will rename every instance of each file (i.e., if unnamed_0711-42_p1.mov appears in multiple subdirectories, each instance will be renamed to day1_0711-42_p1.mov). If you know each file name will only appear once, you can speed things up a bit by adding -print -quit to the end of the find command, before the pipe.

Comments