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).
Recipes
So here are a few of my recipes for managing thousands of files using it (I keep my photos in a YYYY/MM
hierarchy, with only a few sets imported into iPhoto or similar apps).
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
Organizing Photos By Camera Attributes
I’ve recently needed to reorganize a set of folders based on camera model, and came up with this (simply tweak the metadata fields to your liking, and you can organize photos at will):
import os, sys, subprocess, shutil
photos = filter(lambda x: '.jpg' in x.lower(),os.listdir('.'))
for name in photos:
pipe = subprocess.Popen("jhead %s" % name, shell=True, stdout=subprocess.PIPE).stdout
meta = {k: v for k, v in map(lambda x: map(lambda x: x.strip(), x.split(':',1)),pipe.readlines())[:-1]}
folder = meta['Camera model']
if not os.path.exists(folder):
os.mkdir(folder)
shutil.move(meta['File name'], folder)
Generic Automation
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.
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 . " " . $_ );
}
}
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:
renrot -n %Y%m%d%H%M%S *.*
…but I’m not crazy about it.
Downloads
Here are download links for: