Bash Script To Change File Extensions

Ever want to change the file extension for a group of files in one fell swoop? Me too. If you are using a unix-like system (Linux, Solaris, OS X, etc) then this is extremely easy using a Bash script. If you are on a Windows system then stop everything right now and go install the Cygwin environment.

The task at hand is actually pretty easy and can be done as a one liner, but I thought I’d create a more general purpose script. That way I can just use my script the next time I need to rename some files.

The numbers 1, 2 and 3 represent command-line arguments. You’ll see above the first thing I do is store the 2nd argument as the old extension and strip off any leading “dot”. I do the same with the 3rd argument storing it as the new extension. Next I do a find with the first argument being the search directory. Notice the iname option which means it will do a case insensitive name match. I pipe the results of the find into a while loop, calculate the new filename and rename/move the file. That’s it! Below is the full script file which includes a usage statement and some pretty comments.

Note: if the file here doesn’t work for you then you may simply need to retype it. I created the file on a Cygwin environment in Windows and sometimes when you move files from Windows over to a Unix system there are special characters which prevent it from being executed.

  • Ben R

    Thanks for that, Jonathan

    Is there a simple way to adapt the script to accept multiple incoming extensions all at once (say, psd, tif, jpg)

    I’m tying it in with some “sips” usgae on OS X to batch convert entire directory trees to small jpegs.

    Thanks, Ben

  • Bash is very powerful and you can basically tell it to do whatever you want… so sure!

    You could try playing with the find syntax. I was able to get find to get a listing of files with it’s -iregex option, which uses regular expressions to find the files.

    find "${1}" -regextype "posix-extended" -iregex ".*.(psd|tif|jpg)"

    You could hard code the extensions in your find statement or you could pass them in on the command line if you liked.

  • Thanks Jonathan, you’ve saved my day.
    I’ve adapted your script to ‘svn mv’ files by changing extension.
    Honestly, I didn’t know the /# /% syntax inside brackets!

  • Brian D

    In windows there’s no need for Cygwin, this is one of the extremely rare occasions that cmd.exe can actually do something well:

    move *.old *.new

    Works with copy as well.

  • lol – Well, certainly I’m not saying that there is a “need” for Cygwin in Windows, per se. However, I personally am more comfortable in *nix land as far as the command prompt goes. Does Windows have a built regular expression parser (ie Sed)? Nope.

    So basically it comes down to preference. If you like doing things the Windows way then that’s great. If you like Linux/Unix then you can have that too! Thanks for taking the time to comment.

  • fati jalony

    i need some help with this program. i ran your script in Unix Bash but it is telling me that the -iname is a bad option, do u know why, i am using the bash in Unix for enaxple ia put the filename on the command followed by three argument.
    eg . please help. this is my program design.

    Write a bash script that will change the extension of a list of files. This script should accept three or more arguments, according to the following pattern:
    chngext …
    It should then rename all the files in the list of filenames on the command line that end with the suffix ‘oldext’, replacing ‘oldext’ with ‘newext’. The script should print a message for each file named on the command line, indicating either that it is changing the file name (“… from … to …”) or that the file name did not include the specified suffix.