0

I see this command advised, whenever a person asks online about renaming all uppercase files to lowercase:

find "$(pwd)" -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;

I understand the find "$(pwd)" -depth -exec rename part.

Can someone breakdown and explain the regex command of rename - namely: 's/(.*)\/([^\/]*)/$1\/\L$2/'

  • Why \/([^\/]*) and not only (.*)?

  • I know what $1 is in the context of bash, but what does $1, \L$2 mean in rename?

  • I would also appreciate how is this different from a simple

    find "$(pwd)" -depth -exec rename 'y/A-Z/a-z/' {} \;
    
  • Finally, what book or resources would you recommend to learn this kind of stuff? I read the rename man-page; however, I did not find explanations there about this type of usage.

2
  • Useful resource for you at perldoc – bu5hman Jul 11 '20 at 19:35
  • @bu5hman thanks man – z3r0p1r Jul 11 '20 at 21:07
1

The first s/, the last / and the unescaped / in the middle are the substitute operator and the separators, so we have the pattern (.*)\/([^\/]*) and replacement $1\/\L$2.

In (.*)\/([^\/]*) the first (.*)\/ matches everything up to the last slash, that is, the path before the final filename. The last ([^\/]*) then matches anything but slashes up to end of string.

In the replacement, $1 puts back what the first capture group in parenthesis matched, that was the path. Then \L lowercases the following part, the second captured group $2, or the filename.

The end result here is that the lowercasing only applies to the final filename part, so e.g. dir/OTHERDIR/FOO.txt turns to dir/OTHERDIR/foo.txt, not dir/otherdir/foo.txt. Renaming directly to the latter wouldn't work, since dir/otherdir probably doesn't exist.


However... I think you could just run:

find . -depth -execdir rename 'y/A-Z/a-z/' {} +

"$(pwd)" (or more simply, "$PWD") only works to make find produce absolute paths, instead of relative paths, but there's no need for that. -execdir runs rename separately in each directory, instead of all in the main level, getting rid of the problem of dealing with the full paths. And {} + instead of {} \; lets find give more than one file to each invocation of rename.

Though note that all that probably only works for the 26 ASCII letters, not for the rest of the characters found in actual languages (e.g. äöåé).

1
  • @ikkachu thanks - your explanation clears it up – z3r0p1r Jul 11 '20 at 21:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.