5

I'm trying to currently rename a large set of files and have been using quite kludgy methods to do so, such as:

rename 's:(.*)\.MOV:$1.mov:g' *.MOV
rename 's:(.*)\.JPG:$1.jpg:g' *.JPG

What I'd really like to do is to be able to combine all of these commands using the 'y' sed operator. Evidently, using this operator, you can transform items to lower case. The problem is that I need to convert only the extensions. Is there a way to do this using this command? I need to essentially transform the capture group in the following expression to lowercase: ^.+\.(.+)$. Is there a way to do this? I'm kind of new to these kinds of transformations.

Naftuli Kay
  • 39,676

1 Answers1

9

That's the Perl-based rename found on Debian, Ubuntu and derivatives, judging by the syntax. You can't use the tr operator because it acts on the whole string. But you can match the extension, and lowercase it with \L.

rename 's/\.[^.]*$/\L$&/' *.JPG *.MOV

Here it's unnecessary, but if the regexp matched more than the part that you want to lowercase, you could put the part to be matched in a group:

rename 's/\.([^.]*)$/.\L$1/' *.JPG *.MOV

Replace *.JPG *.MOV by *.* to act on all files regardless of extension. In bash ≥4.3 (and also in bash 4.0–4.2, with the caveat that this also traverses symbolic links to directories), you can easily act on files in subdirectories and so on recursively:

rename 's/\.[^.]*$/\L$&/' **/*.*

For the zsh fans (the :r and :e modifiers isolate the extension from the rest of the file):

autoload zmv
zmv '*.(MOV|JPG)' '${f:r}.${(L)f:e}'      # these extensions, current directory
zmv '*.*' '${f:r}.${(L)f:e}'              # all extensions, current directory
zmv '**/*.*' '${f:r}.${(L)f:e}'           # all extensions, recursive directory traversal