How To Rename Multiple Photos and Videos Based on EXIF Data?

I needed to rename my photos and found this question here -- I just found out that exiftool handles it natively:

From http://www.sno.phy.queensu.ca/~phil/exiftool/filename.html

exiftool -d %Y-%m-%d_%H-%M-%S%%-c.%%e "-filename<CreateDate" DIR 

If you want to keep track of original filename and write extension lower case:

exiftool -d %Y%m%d_%H%M%S%%-c-%%f.%%le "-filename<DateTimeOriginal" [.|DIR]

The same works also with the whole filename in lowercase:

exiftool -d %Y%m%d_%H%M%S%%-c-%%lf.%%le "-filename<DateTimeOriginal" [.|DIR]

What I don't like in this renaming method is the colons used in EXIF date and time stamps (e.g. "2013:09:03 20:55:09_IMG_0108.JPG") which might create problems when transferring these files later to other environments (e.g. Windows).

You could run the naming scheme through sed, to replace the colons with dashes and spaces with underscores, like so:

mv -i "$i" "$(exiftool -CreateDate "$i" | awk -F ': ' '{print $2}' | sed -e 's/:/-/g' -e 's/ /_/g')_$i"

As for making the whole thing lowercase, you could use rename:

rename 's/(.*)/\L$1/' file.JPG
##  or
rename 's/(.*)/\L$1/' *.*

Or you could do it within your script using sed, as in:

j=$(echo "$i" | sed -e 's/\(.*\)/\L\1/')

...and then use the $j variable in place of the final $i of your mv line. This sed way is slightly more portable (if that matters to you) as different linux distros have different rename commands, while sed is universal.

Or, alternatively, the script can be modified as follows to perform filename conversion to lowercase at the beginning using tr instead:

for arg 
do
  tmp="$(echo "$arg" | tr '[A-Z]' '[a-z]')"
  mv -i "$arg" "$(exiftool -CreateDate "$arg" | awk -F ': ' '{print $2}' | sed -e 's/:/-/g' -e 's/ /_/g')_$tmp"
done

To perform slightly different commands for different file types, a bash case statement can be used in this script. For example:

#! /usr/bin/env bash
for filename in ./*
do
  tmp="$(echo "$filename" | tr '[A-Z]' '[a-z]')"
  case "$filename" in
    *.MOV|*.mov) 
      mv -i "$filename" "$(exiftool -a -s -CreateDate-tur "$filename" | awk -F ': ' '{print $2}' | sed -e 's/\-[0-9][0-9]\:00//g' -e 's/\+[0-9][0-9]\:00//g' -e 's/:/-/g' -e 's/ /_/g')_$tmp"
      ;;
    *.JPG|*.jpg)
      mv -i "$filename" "$(exiftool -a -s -CreateDate "$filename" | awk -F ': ' '{print $2}' | sed -e 's/:/-/g' -e 's/ /_/g')_"$tmp""
      ;;
    *)
      echo 'Not a *.jpg or a *.mov!'
      ;;
  esac
done

In this example, renaming of MOV files that have CreateDate timestamps ANY NUMBER of hours AFTER OR BEFORE JPG files is adjusted by using another (-tur) EXIF data and removing that that time difference suffix, and it might be necessary to change -tur part according to the location set in the system.


I'd use krename for this. It

  • shows live preview
  • allows undo
  • can go recursively into dir
  • allows multiple rename patterns
  • allows globs and regexps in patterns
  • remembers history