Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

A command to change a set of files' extension UNIX
I have wanted a way to rename all files with one extension to another extension for some time now ... and finally figured out a way to do so without writing a script. The first thing most people think of is something like mv *.txt *.rtf, but that will never work because the targets will not expand the wildcard in that way. Next you might try xargs or find with -exec, but the extension becomes a problem because you can only append to it. The solution: the following command will rename all the files in the folder with the .txt extension to .rtf:
ls *.txt | sed 's/\(.*\)\.txt/  & \1.rtf/' | xargs -L1 mv
This can be applied to other commands like find instead, so be careful:
 find . -name '*.txt' -print | sed 's/\(.*\)\.txt/  & \1.rtf/' | \
 xargs -L1 mv
The above command would run for a whole subdirectory. Depending on where you are in the hierarchy, you could rename all the .txt files on your hard disk! The final command in xargs tells it what to do. You could replace that with something other than mv, like cp or diff; pretty much any command that takes two arguments.

The first part of the command locates the files with the particular extension. The sed command then uses a regular expression to build a set of arguments replacing the original with the replacement. The xargs bit executes the command, once for each line with the arguments generated by sed.

Once again, please be careful with this, it is powerful. You might want to test the final command with echo until you are sure you are getting the right set of files and replacements. So to be safe:
 find . -name '*.txt' -print | sed 's/\(.*\)\.txt/  & \1.rtf/' | \
 xargs -L1 echo mv 
[robg adds: I haven't tested this one...]
    •    
  • Currently 2.00 / 5
  • 1
  • 2
  • 3
  • 4
  • 5
  (3 votes cast)
 
[17,107 views]  

A command to change a set of files' extension | 28 comments | Create New Account
Click here to return to the 'A command to change a set of files' extension' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
The easier way...
Authored by: josephaw on Mar 14, '05 09:58:28AM
I used to do this manually until I found this utility, VersionTracker:R-Name
Used this dozens of times to rename thousands of JPG files in subdirectories.
Joe

[ Reply to This | # ]
A command to change a set of files' extension
Authored by: wgscott on Mar 14, '05 10:02:34AM
If you use the zsh shell provided with os x, you can do the following: autoload -U zmv alias mmv="noglob zmv -W" Then you have a nice command for batch-renaming a set of files, eg, foo.txt bar.txt foobar.txt mmv *.txt *.newsuffix

[ Reply to This | # ]
A command to change a set of files' extension
Authored by: wgscott on Mar 14, '05 10:07:19AM
I apologize for the formatting. There are three commands, the first two can be put into a zsh startup file: autoload -U zmv
alias mmv="noglob zmv -W"
mmv *.txt *.newsuffix


[ Reply to This | # ]
A command to change a set of files' extension
Authored by: adrianm on Mar 14, '05 10:08:48AM

zsh rocks
why oh why did apple change the default shell from tcsh to bash when zsh was available?



[ Reply to This | # ]
bash
Authored by: dr_turgeon on Mar 14, '05 01:07:03PM

I think that bash is the fastest growing shell, very popular with linux folks. zsh is also considered to have feature sprawl.



[ Reply to This | # ]
bash
Authored by: adrianm on Mar 14, '05 04:00:17PM
Agreed. Where zsh really shines is as an interactive shell.

I just love the way I type, eg tar ctab and it knows that it must be followed by f or v and says so...

Scripted completion is great :-)

[ Reply to This | # ]

And yet another way:
Authored by: gidds on Mar 14, '05 10:23:52AM
for FILE in *.txt; do mv $FILE ${FILE%.txt}.rtf; done

This uses a standard shell loop.  The clever bit is the ${FILE%.txt}, which fills in the value of $FILE but strips out any '.txt' suffix from it.  You can also use # instead of % to strip out a prefix instead.

This works in zsh, bash and sh, though not csh.  But, I'm right with the previous poster in thinking that zsh is great and wondering why everyone else isn't using it already!  For example, you can apply this to all .txt in all subdirectories too just by changing the *.txt to **/*.txt.  Neat, huh?

---
Andy/

[ Reply to This | # ]

And yet another way:
Authored by: duelafn on Mar 14, '05 11:23:59AM
You should put double quotes around the variable names:
for FILE in *.txt; do mv "$FILE" "${FILE%.txt}.rtf"; done


[ Reply to This | # ]
And yet another way:
Authored by: LC on Mar 14, '05 08:40:31PM
csh (and tcsh) users --

foreach f (*.txt)
  mv -i ${f} ${f:r}.text
end
csh, tcsh (if you find yourself using it) has those nifty word substitution operators ... Larry.

[ Reply to This | # ]
Alternatively...
Authored by: jwrfoo on Mar 14, '05 10:24:45AM

with zsh:
for i (*.txt) mv $i `basename $i .txt'.xyz

(see man basename for useful info)

... similar for bash etc, but with the more convoluted for... syntax.

---
-j



[ Reply to This | # ]
Alternatively...
Authored by: phil4u2 on Mar 14, '05 01:55:40PM
sorry, but although this is the "easiest understood" command line for a beginner like me, it doesn't work! all I get is
for bquote>
what do I do after that? I had to abort (Command - . )

[ Reply to This | # ]
Alternatively...
Authored by: jwrfoo on Mar 15, '05 04:13:53AM

Ahh... the joys of typing too fast :D

The quotes need to be back quotes i.e. `, so the correct command is:

for i (*.txt) mv $i `basename $i .txt`.xyz

(zsh only, bash is slightly different).

---
-j



[ Reply to This | # ]
A command to change a set of files' extension
Authored by: stebecarp on Mar 14, '05 12:38:01PM

If you choose to stray away from the command line, there is a Finder Script in the default script menu named 'Replace Text In Item Names', which does just that. The script does not accept wildcards, so it could be tripped up by more complicated file names, but it is pretty handy for simple jobs like changing file extensions.



[ Reply to This | # ]
A command to change a set of files' extension
Authored by: haumann on Mar 14, '05 12:42:51PM

Maybe I'm misreading something, but if you're making the changes to items in a given folder, why not just use the "Finder Scripts >Replace Text in Item Names" script that's available in the Scripts menu-bar item of any standard OS X installation?



[ Reply to This | # ]
A command to change a set of files' extension
Authored by: osxpounder on Mar 14, '05 05:51:09PM

I don't think the Scripts menu bar is part of any standard OSX installation. Users must find and install the .menu item that makes the Scripts menu appear. That may ship with OSX, and it may even be on the Apple computer, somewhere, after you've installed OSX with no special options or changes ... but the user still must locate the .menu file in question and double-click it to install the Scripts menu, right?

---
--
osxpounder



[ Reply to This | # ]
A command to change a set of files' extension
Authored by: disinfor on Mar 15, '05 09:35:29AM

The script to install the menu is located in the Applications>AppleScript folder. It's really not that buried.



[ Reply to This | # ]
A command to change a set of files' extension
Authored by: sveinbjornt on Mar 14, '05 02:49:47PM
You might want to check out the setsuffix command line tool. It's part of the osxutils command line utilities.

[ Reply to This | # ]
A command to change a set of files' extension
Authored by: car1son on Mar 14, '05 05:01:50PM

I'd be worried about that command if it encountered matching files with spaces in the name.



[ Reply to This | # ]
a list of file types
Authored by: melomac on Mar 14, '05 05:17:07PM

Is there any way to just have a list of file type and perform a find ?
case unsensitive please and very optimised ?



[ Reply to This | # ]
A command to change a set of files' extension
Authored by: kaih on Mar 14, '05 05:40:49PM

There's also the classic "rename.pl" that does similar things, however it is coded to handle all sorts of strange characters in file names and such things:

http://openlook.org/distfiles/rename.pl

---
--
k:.



[ Reply to This | # ]
A command to change a set of files' extension
Authored by: gdelfino on Mar 15, '05 08:28:51AM

In the Perl Cookbook, there is a recipe for renaming files. I it looks similar to the script you linked, but it is much shorter.

http://www.unix.org.ua/orelly/perl/cookbook/ch09_10.htm

[ Reply to This | # ]
Obligatory perl Reply
Authored by: readparse on Mar 15, '05 12:23:55AM
ls *.rtf | perl -MFile::Copy -lne '($new = $_) =~ s/\.rtf$/\.ext/i;move($_, $new)'

-MFile::Copy - this tells perl to use the File::Copy module (which provides the move() function) -- this is a built-in module

-lne - this is the standard way to call perl on the command line when you pipe output to it and you want it to handle newlines in the expected way. Then you give it the perl code in quotes

This next line is kind of weird looking but it's action-packed... it both assigns the value of $_ to the new variable, $new, and then does a search and replace in the next variable's value. It's searching for ".rtf" at the end of the string (case-insensitive, says the "i" after the slash), and replaces it with the new extention (".ext" in this case).

($new = $_) =~ s/\.rtf$/\.ext/i;

Now we have the old filename ($_, the default variable for the current line of input, and $new, the new and updated filename), so we just call the move() function provided by the File::Copy module.

RP

[ Reply to This | # ]

A command to change a set of files' extension
Authored by: gshenaut on Mar 16, '05 02:14:20AM
Just one more--use find's -exec flag to do the move, something like this:
find . -name '*.jpg' -exec sh -c 'mv "{}" `dirname "{}"`/`basename "{}" jpg`.rtf' ';'
I didn't test this, but it should work.

Greg Shenaut

[ Reply to This | # ]

A command to change a set of files' extension
Authored by: gshenaut on Mar 16, '05 02:17:19AM
Just one more--use find's -exec flag to do the move, something like this:
find . -name '*.jpg' -exec sh -c 'mv "{}" `dirname "{}"`/`basename "{}" jpg`.rtf' ';'
I didn't test this, but it should work.

Greg Shenaut

[ Reply to This | # ]

A command to change a set of files' extension
Authored by: possen on Mar 16, '05 01:22:15PM

By the way, the suggestion (I authored the original post) I posted should work with any shell.



[ Reply to This | # ]
Method I often use
Authored by: victory on Mar 16, '05 06:22:53PM
is this:

ls *.txt | sed -e 's/.*/mv -n "&" "&"/' -e 's/.txt$/.rtf/' | /bin/sh

which is partially based on techniques I've seen here on macosxhints before. A few notes:

  • The doublequotes around the "&"s allows the script to properly handle filenames that may have spaces in them without worrying about escape characters.
  • The mv -n guarantees that mv won't overwrite any existing files with the same target filename (i.e. causes mv file.txt file.pdf to fail if file.pdf already exists. Otherwise mv indescriminately overwrites the file)
  • It's easy to 'preview' the effects of the function above, by simply leaving off the final pipe | /bin/sh which will just print the intended results. A nice way to tell ahead of time what the command will do.


[ Reply to This | # ]
ren-regexp
Authored by: forman on Mar 21, '05 08:01:03PM

I have a very advanced perl script which performs a similar function. It allows one to rename files using regular expressions quickly on the command line. It has a flag for testing to see what the effects will be, sanity checking so it doesn't overwrite files, and progressive color highlighting to see what changes are made as each regular expression is applied.

The perlscript, called "ren-regexp", can be downloaded here. There's even an example provided within a fancy mockup of a MacOS Terminal window on the page. ;)

Michael.

[ Reply to This | # ]
A command to change a set of files' extension
Authored by: kren2000 on Nov 13, '07 09:37:30PM
I wrote a quick shell script to do the same for people who don't want to use zsh as their main shell:
Karen-G4:~/bin karen$ more rnsuffix
#!/bin/zsh
if [ $# == 0 ]; then
  echo "$0: change filename suffixes"
  echo "Usage: $0 oldsuffix newsuffixf "
  echo "e.g.: $0 mp4 mov ==> will rename *.mp4 to *.mov "
  exit
fi


echo autoload -U zmv
echo "noglob zmv -W *.$1 *.$2"

autoload -U zmv
noglob zmv -W *.$1 *.$2

It's ugly but I'm sure some of the gurus here can clean it up.

[ Reply to This | # ]