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?


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

| improve this answer | |
  • Thanks for your answer and pointing me to a link on bash string manipulation! – user4390 Feb 1 '11 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'
| improve this answer | |

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.

| improve this answer | |
  • super! exactly what I needed – JoshP Jun 24 '13 at 21:02
  • I get an error syntax error at (user-supplied code), near ".", when I run this command. – Ryan Gates Jun 6 '17 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.

| improve this answer | |
  • 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 '11 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.

| improve this answer | |
  • 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 '11 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
| improve this answer | |

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.

| improve this answer | |

Your Answer

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