How to clean up file extensions?

Here is one way to do this in Bash:

for i in *; do [ "${i/%MP3/mp3}" != "$i" ] && echo "$i" "${i/%MP3/mp3}"; done

I've used echo here so the command itself doesn't do anything but print pairs of files names. If that list represents the changes you want to make, then you can change echo to something like mv -i -- which will then move your files (and prompt you before overwriting).

Brief Explanation:

The for iterates through every file matched by *. Then, we determine if the extension is already lowercase, if it is we move on, if it isn't, we proceed to move it (or echo it, as the case may be). This uses Bash's built in string operations which you can read about here:

In zsh:

autoload zmv
zmv '(*).MP3' '$1.mp3'   # rename files in the current directory only
zmv '(**/)(*).MP3' '$1$2.mp3'  # rename files in subdirectories as well

To also take care of .Mp3 or .mP3 files:

zmv '(**/)(*).(#i)mp3' '$1$2.mp3'

You could use the rename command (beware there are two main implementations with different APIs) for those. For example to change the case of file name extensions from upper to lower, try this:

  • with rename from util-linux (sometimes called rename.ul), assuming .JPG occurs only once in the file names

    rename -- .JPG .jpg *.JPG
  • with the rename from perl (sometimes called prename; several variants have been published):

    rename 's/\.JPG$/.jpg/' ./*.JPG

Here is some guys tutorial about how he moved from a messy bash script to this simple command for exactly your use-case.

Another fancy command to do this is pax. If you are using ZSH for your shell, you could also use zmv.