2

i have hundreads of folders with a subfolder named "thumbs" under each folder. i need to change the "thumbs" subfolder name with "thumb", under each subfolder.

i tried

find . -type d -exec rename 's/^thumbs$/thumb/' {} ";"

and i run this in shell when i am inside the folder that contains all subfolders, and each one of these subfolders contains the "thumbs" folder that need to be renamed with "thumb".

well I ran that command and shell stayed a lot of time thinking, then i gave a CTRL+C to stop, but I checked and no folder was renamed under current directory, I dont know if i renamed folders outside the directory i was in, can someone tell me where i am wrong with the code?

jo.ker
  • 77
  • 8

1 Answers1

1

Goal 1: To change a subfolder "thumbs" to "thumb" if only one level deep.

Example Input:

./foo1/thumbs
./foo2/thumbs
./foo2/thumbs

Solution:

find . -maxdepth 2 -type d | sed 'p;s/thumbs/thumb/' | xargs -n2 mv

Output:

./foo1/thumb
./foo2/thumb
./foo2/thumb

Explanation:

Use find to give you all "thumbs" folders only one level deep. Pipe the output to sed. The p option prints the input line and the rest of the sed command changes "thumbs" to "thumb". Finally, pipe to xargs. The -n2 option tells xargs to use two arguments from the pipe and pass them to the mv command.

Issue:

This will not catch deeper subfolders. You can't simple not use depth here because find prints the output from the top and since we are replacing things with sed before we mv, mv will result in a error for deeper subfolders. For example, ./foo/thumbs/thumbs/ will not work because mv will take care of ./foo/thumbs first and make it ./foo/thumb, but then the next output line will result in an error because ./foo/thumbs/thumbs/ no longer exist.

Goal 2: To change all subfolders "thumbs" to "thumb" regardless of how deep.

Example Input:

./foo1/thumbs
./foo2/thumbs
./foo2/thumbs/thumbs
./foo2/thumbs

Solution:

find . -type d | awk -F'/' '{print NF, $0}' | sort -k 1 -n -r | awk '{print $2}' | sed 'p;s/\(.*\)thumbs/\1thumb/' | xargs -n2 mv

Output:

./foo1/thumb
./foo2/thumb
./foo2/thumb/thumb
./foo2/thumb

Explanation:

Use find to give you all "thumbs" subfolders. Pipe the output to awk to print the number of '/'s in each path plus the original output. sort the output numerically, in reverse (to put the deepest paths on top) by the number of '/'s. Pipe the sorted list to awk to remove the counts from each line. Pipe the output to sed. The p option prints the input line and the rest of the sed command finds the last occurrence of "thumbs" and changes only it to "thumb". Since we are working with sorted list in the order of deepest to shallowest level, this will provide mv with the right commands. Finally, pipe to xargs. The -n2 option tells xargs to use two arguments from the pipe and pass them to the mv command.

keda
  • 559
  • 2
  • 12