简体   繁体   中英

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 (eg unnamed_0711-42_p1.mov ), to the name in field 2 (eg 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?

Below script

while IFS=, read -ra arr # -r to prevent mangling backslashes
do
 find . -type f -name "${arr[0]}" -printf "mv '%p' '%h/${arr[1]}'" | bash
done<csvfile

should do it.


See [ find ] manpage to understand what the printf specifiers like %p,%h do

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
    while IFS= read -r -d '' old_file; do
        old_dir=$(dirname "$old_file")
        mv "$old_file" "$old_dir/${arr[1]}"
    done < <(find . -name "${arr[0]}" -print0)
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 (ie, 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM