Search code examples
regexshellfindrenameglob

How do I Find patterns in both the Directory and Filename and perform a rename on the file only if the pattern is found for the parent directory?


What I am trying to do is rename the files, but only if the parent directory of those files matches a given pattern.

What I am wanting to do specifically is when the partent directory is cd1 or cd2 then insert 1_ or 2_ at the start of the filename.

For example I have:

./Documentary/Arctic/cd1/01 - Penguin
./Documentary/Arctic/cd1/02 - Polarbear
./Documentary/Arctic/cd2/01 - Whale
./Documentary/Arctic/cd2/02 - Walrus
./Documentary/Jungle/01 - Tiger
./Documentary/Jungle/02 - Monkey

and I want to change it to this:

./Documentary/Arctic/cd1/1_01 - Penguin
./Documentary/Arctic/cd1/1_02 - Polarbear
./Documentary/Arctic/cd2/2_01 - Whale
./Documentary/Arctic/cd2/2_02 - Walrus
./Documentary/Jungle/01 - Tiger
./Documentary/Jungle/02 - Monkey

I have done similar replacements such as the one below, however It does not take into account the parent directory:

rename "1 - 10 episode name" to "1_10 episode name":

find . -type f -name '[[:digit:]] - [[:digit:]][[:digit:]] *' -execdir prename -n 's/(.*\/\d) - (\d\d .*)/$1_$2/' {} +

UPDATE: I made some progress on this. I can now find the files by using the "wholename" option, I am now trying to work out the rename part.

find . -depth -wholename '*/cd[[:digit:]]*/[[:digit:]][[:digit:]]*'

Solution

  • Figured it out, YAY! This one was a tough one for me, but im slowly learning.

    find . -depth -type f -iwholename '*/cd[[:digit:]]*/[[:digit:]][[:digit:]]*' -exec prename -n 's/(.*\/[cC][dD])(\d)(.*\/)(\d\d .*)/$1$2$3$2_$4/g' {} +
    

    Additionally if you then wanted to move the renamed files up a level:

    find . -depth -type f -iwholename '*/cd[[:digit:]]*/[[:digit:]]_[[:digit:]][[:digit:]]*' -execdir mv {} .. \;