bms9nmh bms9nmh - 3 months ago 6
Linux Question

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

I have a

file in which looks something like this:,,,,

I have written this code to rename files from the name in field 1 (e.g.
), to the name in field 2 (e.g.


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

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


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

for D in `find . -type d`
    cat $csv | while IFS=, read -r -a arr; do mv "${arr[@]}"; 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:

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]}"

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 appears in multiple subdirectories, each instance will be renamed to 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.