I have a directories with .MP3 files which I'd like to change the extensions to .mp3. What's the easiest way to do this? I'm think something along the lines of:

find /RootPath -type f -iname "*.mp3" -exec mv {} sed s/.*MP3/\1.mp3/ \; 

...though I know that isn't quite right. :) The substitution isn't correct and I'm not sure how to use both a mv and a sed command with -exec in find.

Would I need a bash script for this?


7 Answers 7


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: http://tldp.org/LDP/abs/html/string-manipulation.html

  • Thanks for your answer and pointing me to a link on bash string manipulation!
    – user4390
    Feb 1, 2011 at 22:03

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.

  • super! exactly what I needed
    – JoshP
    Jun 24, 2013 at 21:02
  • I get an error syntax error at (user-supplied code), near ".", when I run this command.
    – Ryan Gates
    Jun 6, 2017 at 1:31

Use perl-rename, swiss army knife of file-renaming with regular expressions (on ubuntu, this is bundled with the perl package as prename):

# Replace prename as appropriate (i.e. if you've got it installed under a different name
find /RootPath -type f -iname '*.mp3' -print0 | xargs -0 prename 's/mp3$/mp3/i'

If you're of the careful sort, use the -n and -v options to perl rename to see what it'll actually do.

  • Thanks for your answer. Don't have perlrename on the server, but I'm going to be playing around it with it later today!
    – user4390
    Feb 1, 2011 at 22:03

You need a script, because "extensions" under Linux are actually just parts of the file name string. You have to do some string manipulation in the script to get the new name.

for NAME in *.JPG
    mv "$NAME" "$NEWNAME"

The double-quoting is important if you've got file names with whitespace in them. I thought some of the double-quoting was a bit inobvious.

  • 1
    There is nothing wrong per-say with your script but you very defiantly don't need a script for this. There are probably a dozen ways to do it on one line in most shells, and lots of utilities to make it easy too.
    – Caleb
    Jun 11, 2011 at 19:43

In bash:

# renaming files in the current directory only
for f in *.MP3; do mv "$f" "${f%.MP3}.mp3"; done  

# renaming files in subdirectories as well
for f in *{,/*}.mp3; do mv "$f" "${f%.MP3}.mp3"; done

first back up your files! you can use a python one-liner:

python -c "import glob,os; [os.rename(fn, fn.replace('.MP3', '.mp3')) for fn in glob.glob('PATH_TO_YOUR_DIRECTORY')]"


Here is a detailed explanation of how the one-liner actually works. Using python -c we are passing a command to the python interpreter. After importing the libraries os for the rename function and glob for file listing, we need to iterate through the file list in the given directory, which I called PATH_TO_YOUR_DIRECTORY, for example something like ./* for everything in the current directory.

In the one-liner syntax unfortunately for loops don't work after import notation, so we need to use the bracket notation. I.e. for every file or directory name that glob is giving us from the given path in form of a string, we replace *.MP3 to *.mp3.

Since OP did not mention recursive search, I did not include it in the first place.


You must log in to answer this question.