Identifying portrait/landscape in a set of images, with ImageMagick and BASH

I haven’t written much BASH of late, so was a bit rusty. The goal? A script that would go through a directory of JPGs, find those that are portrait shots, and place them in an appropriate folder. Do so similarly for landscapes.

Use cases? Those new digital photo frames. Buy two, and have many images scroll by, eh?

What’s been done?
Making use of ImageMagick’s identify is what needs to be done. You’ll be using the -format option, which normally takes a type or string. A full list of what options are available for -format are available.

The choice is to use -format '%[exif:orientation]'. The output of identify -format '%[exif:orientation]' is either:

  • 1 – portrait
  • 6 – landscape
  • 8 – portrait (the way I normally shoot, with the battery grip)

I’ve not seen much documentation about the above, so it seems like these values come from trial and error… They apply for Canon cameras that have EXIF orientation details. I’d be interested to hear from others what values they’re getting (or getting pointed to some documentation).

The shell script?

#!/bin/sh

mkdir portrait
mkdir landscape

for i in *.jpg;
	do
	type=$(/opt/local/bin/identify -format '%[exif:orientation]' $i)
case $type in
	1)
	mv $i portrait;;
	6)
	mv $i landscape;;
	8)
	mv $i portrait;;
esac
done

Other bits of BASH?
If you do: type=$(/opt/local/bin/identify -format '%[exif:orientation]' $i) , you can grab the value from the command (1, 6, 8) and manipulate it. Check by doing echo $type.

If you’re after getting the return value from a command (i.e. 0 for success, 127 for error, and so on), you can do echo rv: $?.

All in all, remember to read the BashFAQ. Tests and Conditionals was also essential to my reading.

ImageMagick rocks nonetheless. I’ve used it before to resize, append and much more… I’m thinking that maybe its time to read The Definitive Guide to ImageMagick, written by Mikal.

  • use “set -e” at the top of the script, and
    mkdir -p to not fail if those directories already exist as directories.

    Then if one of the mkdirs fail because they already exist as a *file*, then the subsequent mvs won’t be executed, which is a very good thing, because otherwise you will end up repeatedly mving many files over the top of one file, and thus losing all but the last one of those files. Yes, a colleague has done this running one of my scripts that wasn’t defensive enough, without performing the tests I was expecting him to perform first. No, we didn’t have backups.

    (alternatively, I would also consider using the construct
    ‘yes no | mv -i “$source” “$dest”, which would negate the suggestion of using set -e, since it will simply refuse to overwrite anything anyway)

    P.S. Quote your “$i” :)

    Defensive shell scripting is good, mmmkay? :)

  • Whats up?
    savonius turbine savonius turbine
    sayula sayula
    That is my blog. Visit it, please.
    c U.

  • limazita

    I get the following error when running the script :

    dyld: Library not loaded: /ImageMagick-6.4.8/lib/libMagickCore.2.dylib
    Referenced from: /Applications/ImageTools/ImageMagick-6.4.8/bin/identify
    Reason: image not found

    I install it on my mac following the instructions on the ImageMagick site. I did the verification of the logo.gif test and it seems the installation is ok.

    Any Idea for the error?


i