Handy script to rename multiple files on a Mac / Unix-based system

As a photographer, one of the frequent operations I require to do is to rename multiple files in a directory – I generally add date and the location where I took the photograph as part of the selection process.

For Windows users, the wonderful Irfan View’s batch rename feature can perform this task very quickly, and one does not need to know much of scripting / tweaking. Just select the parameters, hit the button and you’re done. I couldn’t find a similar application that could perform batch renaming operations on a Mac with ease. It can be very frustrating to manually rename a bunch of files.

I came up with a script that one can run on a console, that performs batch renaming operation. Pre-requisites are that you would have to manually sort out the files into folders based on your requirements and all files should have the same file extension. For example, if you have a bunch of files to whose names you would like to add ‘Bangalore’ and another set to which you would like to add ‘Mysore’ – you have to keep them in separate folders, and all of the should have ‘.jpg’ (or any other type) as their file extension. You can check the file extensions quickly by issuing a ‘ls’ command and checking if the characters after the last ‘.’ are the same. You can have multiple ‘.’ in the file name, but the characters that follow the last ‘.’ should be the same.

Open ‘Terminal’ application [Application -> Utilities -> Terminal] or press ‘Command (Apple key) + Space’ and type ‘Terminal’ (without the quotes) and press the Enter key. Navigate to the folder using ‘cd <<Folder_name>>’ command, and type this:

for file in ./*; do mv $file <<DATE>>`basename $file .<<FILE_EXT>>`”_<<LOCATION>>.<<FILE_EXT>>”; done

Replace <<DATE>> with date (or anything else you’d like to prefix) and <<LOCATION>> with location name, <<FILE_EXT>> with the file extension and press enter. This will rename all the files present in that folder.

Example: If you have the following files in ./tmp folder:
IMG1.jpg
IMG2.jpg
IMG3.jpg
IMG4.jpg
IMG5.jpg
IMG6.jpg

Use the following set of commands:
cd ./tmp
ls

IMG1.jpg IMG3.jpg IMG5.jpg
IMG2.jpg IMG4.jpg IMG6.jpg

for file in ./*; do mv $file 2011_07_02_`basename $file .jpg`”_Bangalore.jpg”; done
ls

2011_07_02_IMG1_Bangalore.jpg 2011_07_02_IMG3_Bangalore.jpg 2011_07_02_IMG5_Bangalore.jpg
2011_07_02_2011_07_02_IMG2_Bangalore.jpg 2011_07_02_IMG4_Bangalore.jpg 2011_07_02_IMG6_Bangalore.jpg

There, that’s done.

For the curious, here’s what the script does:

for file in ./*; do mv $file 2011_07_02_`basename $file .jpg`”_Bangalore.jpg”; done

This executes three commands, one after the other. Let us go through it one by one:

for file in ./*

This statement is an iterator – it populates the variable file with the name of every file present in the current directory, one after the other. [Current directory is represented by ./ and the * is a wildcard that stands for all files]

do

Indicates the start of the iterations

mv $file 2011_07_02_`basename $file .jpg`”_Bangalore.jpg”

This statement is the logic behind renaming the files. This statement uses two native commands:
mv is a command that moves files from one location to another. We are using this command to rename files, since some distributions do not support a native command to rename files.
basename is another command that extracts only the name of a file, if we provide the extension. The iterator will give the full file name, which means the file extension will be present in file variable. ‘.jpg’ is the extension that we are attempting to remove from the file name. As an example, if we have IMG1.jpg basename IMG1.jpg .jpg will print IMG1 on the console.
If your system does not support these two commands, you will have to find equivalents that get the job done.

Now that you know about mv and basename, it should be fairly easy to understand the rest of the statement. $file will fetch the value that the variable file contains. basename command extracts only the file name. We are essentially moving the file whose name is present in file variable to a new file name as specified by the second parameter, which will be concatenated. The diacritical marks tells that the shell interpreter will have to take the output of what’s between them (Please note – it’s diacritical mark, the key above the Tab, to the left of 1 key on your keyboard, and not a single quote). Our format here specifies the interpreter to insert the date, file name & the location with the file extension. Not so complicated, isn’t it?

done

This closes the iteration sequence and the for statement will fetch the next file name into file variable, the sequence is repeated till the iterator runs out of files to process in the current directory.

And if you are asking how the statement doesn’t run into an infinite loop since you will always have files in the directory, the iterator statement will consider the names of the files when you first executed it, and does not scan the folder for changes.

Hope this helps. And as I mentioned earlier, this script is not subjected to renaming images – you can rename any group of files with a slight modification of this script.

Enhancement options: Extract the file extension so that the user need not worry about entering the correct extension – I’m a little too lazy to work on that now.

And if you have any questions, leave a comment and I’ll respond to it. And if you also have other ways to do the same operation, do let me know – I would be interested in knowing how to do this efficiently.

PS : This script was put together with ideas from various forums and other blogs that I went through in trying to find a solution for my problems. You are free to use it, enhance it, redistribute it without any acknowledgement whatsoever. This is safe to use, and I’ve been using it for a while now without any problems. However, I will not take responsibility for any problems that come out of using this script directly or by modifying it.


3 Responses to “Handy script to rename multiple files on a Mac / Unix-based system”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.