Originally created 11/1999; Moved to Lab 12/2001; Updated 07/06/2004

Batch File Rename By File Extension in Unix

These are one-liners which batch rename files meeting a certain criteria under unix

These are very powerful command line tools. They have been used on FreeBSD, Linux, and MacOSX with success. But as with any batch file changing, you are advised to use them with caution. Backups are your friend!

# change .htm files to .html
for file in *.htm ; do mv $file `echo $file | sed 's/\(.*\.\)htm/\1html/'` ; done

# change .html files to .htm
for file in *.html ; do mv $file `echo $file | sed 's/\(.*\.\)html/\1htm/'` ; done

#change .html files to .shtml
for file in *.html ; do mv $file `echo $file | sed 's/\(.*\.\)html/\1shtml/'` ; done

#change .html files to php
for file in *.html ; do mv $file `echo $file | sed 's/\(.*\.\)html/\1php/'` ; done

More Notes

Visitor Chris Hancock / itoph.com writes in with a question, and answers it himself

(Your page) definitely helped me... but I'm still stuck.

I have Mac OS X, and I need to rename a directory with files like:

[itoph:Coda] toph% ls -l
total 59576
-rw-r--r--  1 toph  staff  4140123 Apr 18 09:43 Bonzo's Montruex
-rw-r--r--  1 toph  staff  4914598 Apr 18 09:43 Darlene
-rw-r--r--  1 toph  staff  4131343 Apr 18 09:43 I Can't Quit You Babe
-rw-r--r--  1 toph  staff  2260992 Apr 18 09:43 Ozone Baby
-rw-r--r--  1 toph  staff  2917166 Apr 18 09:43 Poor Tom
-rw-r--r--  1 toph  staff  4331548 Apr 18 09:43 Walter's Walk
-rw-r--r--  1 toph  staff  2521786 Apr 18 09:43 We're Gonna Grove
-rw-r--r--  1 toph  staff  5264433 Apr 18 09:43 Wearing and Tearing

Based on your page I've got this:
[itoph:Coda] toph% more test.sh
for i in * ; do
echo mv \'$i\' \'$i.mp3\'
done

That doesn't work because of the 's in the file names.  If I leave out
the \'s in the shell script the spaces in the file names cause a problem.

He then follows up with:

I figured it out.  This is the shell script that works:

[itoph:Coda] toph% more t.sh
for i in * ; do
echo mv \"$i\" \"$i.mp3\" | sh
done

It looks a bit weird.  Why wouldn't I just do this:

[itoph:Coda] toph% more t.sh
for i in * ; do
mv \"$i\" \"$i.mp3\"
done

Well, the reason is because it doesn't work.  I get this error:

usage: mv [-fi] source target
       mv [-fi] source ... directory

I don't understand how echoing and piping it to the shell is any
different, but, it works.

Any ideas?

To which I reply: Chris, I have no idea. The command line still manages to mystify me utterly. Congrats on finding the solution to your problem so well! Perhaps your insight will help others!

Reader Michael Dinsmore adds:

I found your page "https://artlung.com/lab/other/unix-batch-file-rename/" when I searched on "batch rename"; found it useful.

Just as I was getting the hang of it, and looking to make it a tidy AppleScript, I discovered that Apple already provided many of those same tools. At least after the developer tools have been installed; I'm not sure if that's required.

Take a look at /Applications/AppleScript/Example Scripts/Finder Scripts. I found a script that will add extensions and prefixes, as well as one that will do wildcard renaming. Very useful!

My reply: Thanks Mike!

Reader Tony A. Lambley has a solution to fixing the "spaces in names" problem. He writes:

Regarding the problem mentioned on: http://lab.artlung.com/other/unix-batch-file-rename/ using BASH you can append .mp3 and get rid of those ghastly embedded spaces with:
for e in *; do mv "$e" "`echo $e | sed -e 's/\ /_/g'`.mp3"; done

before:
$ l
Bonzo's Montruex
We're Gonna Grove

after:
$ l
Bonzo's_Montruex.mp3
We're_Gonna_Grove.mp3

And I reply: Thanks so much Tony. Very impressive solution!

Reader Kurt sends this reply about the tool "basename":

the classic basename(1) tool works very nicely without all of the sed ugliness:
# rename every *.htm file *.html
for f in *htm ; do mv $f `basename $f htm`html; done"
Hope you find this helpful.

Thanks Kurt! Here's a link for basename from gnu.org.


From "Anonymouse" on June 3, 2005:
[itoph:Coda] toph% more t.sh
for i in * ; do
echo mv \"$i\" \"$i.mp3\" | sh
done

It looks a bit weird. Why wouldn't I just do this:

[itoph:Coda] toph% more t.sh
for i in * ; do
mv \"$i\" \"$i.mp3\"
done

It's to do with how the shell does its processing before it passes the args to the command. In the first example, the shell is parses the occurances of \" before giving them to echo, which gives this (which is actually the easy way to do this):

mv "$i" "$i.mp3"
which then gets parsed again by the shell for the | sh to finally pass the command these args (where <filename> is the expansion of $i):
<filename> <filename>.mp3
In the second case, the command gets parsed just once by the shell, which passes these args to the command:
"<filename>" "<filename>.mp3"

The command does not discard the quotes - it treats them as part of the filename, and therefore fails.

It's easily overlooked, but once you understand how the shell is parsing things before they get to the command (ie, it parses * into a list of files in the current directory), a lot of things will fall into place.


Tom Kelshaw wrote in April 6, 2009:
I came across it via Google search for batch renaming files. My requirement was actually to remove garbage/octal chars that had appeared via bad Input file text. Your command suggestions were excellent, but didn't answer my question, whereas after about 4 more hours, this did: http://lists.xiph.org/pipermail/vorbis/2007-August/026974.html Potentially you could add a P.S linking to this listserv post about how to remove garbage chars from filenames? Thanks for all your help and a great site,