Thursday, December 27, 2007

Renaming or changing extension of multiple files at once

In a lot of time you want to rename multiple files at once, or maybe change their extension. My Sony camera names files with the extension .JPG which is really annoying!!! I'd love to have it as .jpg or maybe something else. Further, the camera naming scheme is DSCxxxx.JPG where xxxx is for the number of the image, and I'd like to have some custom name instead. So, how to do this?

First, let us start off with an introduction about file naming and shell scripts. Mass file renaming is a pretty common task among everybody and a lot of people do it in many situations, such as the Sony camera situation, or maybe you have so many files in one directory what you want to rename to something else. Examples of these cases are endless, so let us start with file renaming and some of the available tools to do that without wasting time discussing situations.

The BASH shell provides many useful tools for renaming multiple files. Please note that I'm not claiming that BASH shell is the best. I think that the Z shell might provide more tools, but it is so complex for me :)
One tool you can use in bash to rename multiple files is combining the UNIX command mv with a for loop like this:
for file in .; do mv $file hello; done
well... this is not useful.. in face this is disastrous this will rename all files in the current directory to hello, not only this, but also you'll have one file in that directory called hello. Poor you, nothing left to celebrate, no more old memories and nice moments taken by camera, because you've formatted your memory stick :) So let's not do this at all.

Alright, let's say you just want to rename all files in the current directory to holiday_xxxx.jpg, where xxxx is the serial number for a photo, starting from 0000 up to 9999 (of FFFF if your prefer hex)
Let us do that

#!/bin/bash
prefix="holiday"
i=0
for file in *.jpg; do
num=`printf "%.4d" "$i"`
let "i += 1"
mv $file "$prefix_$num.jpg"
done

And that is it we are done. We can also take the prefix as a command line argument and thus use this script in any place where we want to rename jpg photos:
#!/bin/bash
if [ -z "$1" ]; then
echo "please supply a prefix(name) argument"
exit
fi

prefix="$1"
i=0
for file in *.jpg; do
num=`printf "%.4d" "$i"`
let "i += 1"
mv $file "$prefix_$num.jpg"
done

Cool.. now let's explore another tool.. basename. You can use basename like in situations like this:
nitro$ basename /usr/bin/perl
nitro$ perl

Another useful use is when you supply a suffix to basename like this
nitro$ basename hello.jpg .jpg
nitro$ hello
nitro$ basename hello.jpg jpg
nitro$ hello.
nitro$ basename hello.jpg g
nitro$ hello.jp

So, to lowercase a lot of .JPG file you can do this:
nitro$ for file in *.JPG; do mv $file "`basename $file .JPG`.jpg"; done

in my opinion, the easiest is this one, which is using the built in bash variable substitution
for file in *.JPG; do mv $file ${file/.JPG}.jpg; done

Some good source to look @ http://www.debian-administration.org/articles/150

No comments: