Loopy loop

Last time I blogged about a very useful feature in bash – a for loop. Here comes the second part. We will take care of batch file renaming this time.
With couple of additional, standard tools, you can build ultimate tool for renaming files. Unlike the GUI solutions which are only as good as what the author thought would be useful, in shell you can do anything. You are the author!
Let's first tackle filename extension changing. Say you've got 20 javascript files you want to become templates in your CMS system:

$ ls
array.js date.strftime.js utils.js

We will need a handy small tool for our task: basename
This is how it works:

$ basename utils.js .js
utils

The last param is the optional suffix you want Stripped. This way we can obtain clean filename without any suffix and replace it with a new one.

for file in *js
do
        echo $file
        mv $file `basename $file .js`.tpl
done

See what happens here? We loop through all the files renaming each one of them to its basename (backticks is inline command execution) concatenated with a new extension. Simple!

From here it's easy. How about renaming all the JPGs in current dir to their respective exif time? Very useful for sorting pictures timewise. Let's check how exiftool works:

$ exiftool -CreateDate phot0003.jpg
Create Date : 2004:03:28 18:29:38

Let's adjust the format a bit:

$ exiftool -d "%Y%m%d_%H%M%S" -S -s -CreateDate phot0003.jpg
20040328_182938

Looks good now, sorting will be in the order pictures were taken.

for file in *jpg
do
        echo $file
        mv $file `exiftool -d "%Y%m%d_%H%M%S" -S -s -CreateDate $file`.jpg
done

You can see the pattern already.

(The above, simple solution has one drawback, it will overwrite pictures which were taken at the exact same second. Solving this I leave up to you. You will probably need to make yet another loop inside… But hey, it's all about loops here).

One more useful thing, especially when transferring files from non-linux filesystems is changing all the filenames to lowercase (or uppercase if you wish). Easy way to do this is:

for file in *
do
        mv $file `echo $file | tr [:upper:] [:lower:]`
done

(As with every simple solution beware of its shortcomings: this one will change also directory names and overwrite possibly created duplicates, i.e. when lowercase named file already exists. Add -i option to mv to be asked before overwrite).


This entry was posted on Monday, November 19th, 2007 at 12:03 pm and is filed under Tips & Tricks. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a Reply