Pragmatism in the real world

Setting title and caption with exiftool

I recently needed to change the title and caption of some photos, so I turned to exiftool as it’s the Swiss Army knife of image metadata.

It’s a lovely tool with many options, so I wrote a script to make it easy and while I was there, used read to prompt me for the info to set. This is the script:

~/bin/exif-set:

#!/usr/bin/env bash

# determine current values
IMAGE_TITLE=$(exiftool -s3 -iptc:ObjectName "$1")
IMAGE_DESCRIPTION=$(exiftool -s3 -iptc:Caption-Abstract "$1")
IMAGE_KEYWORDS=$(exiftool -s -s -s -iptc:Keywords "$1")

# Ask user for new values
read -e -p "Title [$IMAGE_TITLE]: " NEW_TITLE
read -e -p "Description [$IMAGE_DESCRIPTION]: " NEW_DESCRIPTION
read -e -p "Keywords [$IMAGE_KEYWORDS]: " NEW_KEYWORDS

# set to defaults if we got a blank result
NEW_TITLE="${NEW_TITLE:-${IMAGE_TITLE}}"
NEW_DESCRIPTION="${NEW_DESCRIPTION:-${IMAGE_DESCRIPTION}}"
NEW_KEYWORDS="${NEW_KEYWORDS:-${IMAGE_KEYWORDS}}"

# Update
exiftool \
    -overwrite_original \
    -iptc:ObjectName="$NEW_TITLE" \
    -iptc:Caption-Abstract="$NEW_DESCRIPTION" \
    -iptc:Keywords="$NEW_KEYWORDS" \
    "$1"


# display what we've set
exiftool -f \
    -iptc:ObjectName \
    -iptc:Caption-Abstract \
    -iptc:Keywords \
    "$1"

There’s a few interesting things that I’d like to point out. Firstly we use exiftool to find the current values of the three properties I care about. e.g. for the title:

IMAGE_TITLE=$(exiftool -s3 -iptc:ObjectName "$1")

The IPTC property names are a little opaque, which is partly why I wanted a script as I’m highly unlikely to remember that the title is the ObjectName property! The -s3 (very very short) flag returns just the text of the property with no label as that’s what I want to store in the variable. It’s a nice feature as I appreciate that I don’t have to pipe through sed or awk to extract just the part I want.

Prompting for a new value is done using read. I decided that I also wanted a blank entry (i.e. just pressing return) to indicate that I wanted to keep the current value. This is done using the handy :- parameter subsitution feature of bash:

read -e -p "Title [$IMAGE_TITLE]: " NEW_TITLE
NEW_TITLE="${NEW_TITLE:-${IMAGE_TITLE}}"

We now have the values to set which are either new values typed in via read or the original values, so I can just write then back to the file:

exiftool \
    -overwrite_original \
    -iptc:ObjectName="$NEW_TITLE" \
    -iptc:Caption-Abstract="$NEW_DESCRIPTION" \
    -iptc:Keywords="$NEW_KEYWORDS" \
    "$1"

With exiftool, it know you want to write the meta data by the = assignment of a value to the property name. By default it will create a copy of the original file first before modifying. I don’t need this copy, so -overwrite_original prevents a proliferation of files that I would then have to delete

That’s it

I now have a handy command line tool that allows me to change the title, caption and keywords of a photo easily. Job done!

7 thoughts on “Setting title and caption with exiftool

  1. This is just what I've been looking for. However, I use Windows 10 and do not recognize this script. Is it AppleScript? How hard would it be to write it in Windows PowerShell?

    1. It's in shell script, but as it's just manipulating a command line tool, I imagine that porting to PowerShell is do-able.

    1. Dan,

      I have a script that contains this:

      for file in "$@"
      do
          FILENAME=${file##*/}
          echo "Processing $FILENAME"
      
          # Determine year of copyright
          YEAR=`exifool -S -s -d "%Y" -DateTimeOriginal "$file"`
      
          # Add Exif information to master file
          exifool \
              -m \
              -Copyright="Copyright $YEAR Rob Allen. All Rights Reserved" \
              -IPTC:CopyrightNotice="Copyright $YEAR Rob Allen. All Rights Reserved" \
              -XMP:Rights="Copyright $YEAR Rob Allen. All Rights Reserved" \
              -CreatorWorkEmail="rob@akrabat.com" \
              -CreatorCity="Worcester" \
              -CreatorCountry="UK" \
              -By-line="Rob Allen" \
              -UsageTerms="For consideration only, no reproduction without prior permission" \
              -overwrite_original \
              "$file"
      done
      
      echo "All done"
      

Comments are closed.