Change file extensions of multiple files in a directory with terminal/bash?

CokePokes picture CokePokes · Dec 18, 2011 · Viewed 11k times · Source

I'm developing a simple launchdaemon that copies files from one directory to another. I've gotten the files to transfer over fine.

I just want the files in the directory to be .mp3's instead of .dat's

Some of the files look like this:

6546785.8786.dat
3678685.9834.dat
4658679.4375.dat

I want them to look like this:

6546785.8786.mp3
3678685.9834.mp3
4658679.4375.mp3

This is what I have at the end of the bash script to rename the file extensions.

cd $mp3_dir
mv *.dat *.mp3
exit 0

Problem is the file comes out as *.mp3 instead of 6546785.8786.mp3

and when another 6546785.8786.dat file is imported to $mp3_dir, the *.mp3 is overwritten with the new .mp3

I need to rename just the .dat file extensions to .mp3 and keep the filename.

Ideas? Suggestions?

Answer

fge picture fge · Dec 18, 2011

Try:

for file in *.dat; do mv "$file" "${file%dat}mp3"; done

Or, if your shell has it:

rename .dat .mp3 *.dat

Now, why your command didn't work: first of all, it is more than certain that you only had one file in your directory when it was renamed to *.mp3, otherwise mv would have failed with *.mp3: not a directory.

And mv does NOT do any magic with file globs, it is the shell which expands globs. Which means, if you had this file in the directory:

t.dat

and you typed:

mv *.dat *.mp3

the shell would have expanded *.dat to t.dat. However, as nothing would match *.mp3, the shell would have left it as is, meaning the fully expanded command is:

mv t.dat *.mp3

Which will create a file named, literally, *.mp3.

If, on the other hand, you had several files named *.dat, as in:

t1.dat t2.dat

the command would have expanded to:

mv t1.dat t2.dat *.mp3

But this will fail: if there are more than two arguments to mv, it expects the last argument (ie, *.mp3) to be a directory.