jhead

jhead is my tool of choice for command-line manipulation of images using EXIF tags on all platforms. Whoever is into Digital Photography in earnest will appreciate the ease with which it can perform batch operations with images (it also uses jpegtran to autorotate appropriately tagged images losslessly).

Command-lines for canonical timestamps and scaling:

# basic rename

jhead -exonly -nf%Y%m%d%H%M%S *.jpg

# invoke jpegtran for lossless rotation (useful when your software doesn't understand EXIF orientation)

jhead -exonly -autorot -nf%Y%m%d%H%M%S *.jpg

# batch resize

jhead -cmd "mogrify -resize 800x800 -quality 100 &" *.jpg

Alternatives

There is also an XML-enhanced version and an alternative Perl utility called renrot available as an Ubuntu package that has the slight advantage of (for the particular purpose of managing timestamps) letting you rename any file according to timestamp (very useful for movies and suchlike).

It can be invoked in a very similar fashion as to the above:

renrot -n %Y%m%d%H%M%S *.*

Automating Things

I now use an Automator workflow with the following Python bit inside:

from time import gmtime, strftime, localtime
import sys, os, re

pattern = re.compile(".+\.(jpg|mov|avi|mp4)$", re.IGNORECASE)
paths = []

def rename(f,p,c,e,alt=''):
  n = "%s/%s%s.%s" % (p,c,alt,e.lower())
  if f == n:
    print f
    return
  if os.path.exists(n):
    if alt is '':
      alt='a'
    else:
      alt=chr(ord(alt)+1)
    rename(f,p,c,e,alt)
  else:
    os.rename(f,n)
    print n

for f in sys.stdin:
  f = f.strip()
  matches = pattern.match(f)
  if matches:
    e = matches.group(1).lower()
    p = os.path.dirname(f)
    if p not in paths:
      paths.append(p)
    c = strftime("%Y%m%d%H%M%S",localtime(os.path.getmtime(f)))
    rename(f,p,c,e)
    

for p in paths:
  os.chdir(p)
  os.system('jhead -exonly -nf%Y%m%d%H%M%S *.jpg')

…that I save as a plugin for the built-in Image Capture app.

Here are download links for:

Perl snippet to tag Minolta (mis-stamped) images:

#!/bin/perl

opendir(DIR, ".") or die("directory open error: $!");

foreach(readdir(DIR)) {
  if( /PICT00([0-9]+)\.JPG/ ) {
    system( "jhead -ts2004:05:20-12:00:" . $1 . " " . $_ );
  }
}