Sep 08

Change EXIF date/times and file timestamps with exiftool

Category: Linux,multimedia   — Published by goeszen on September 8, 2015 at 8:07 pm


In case you forgot to set the internal clock of your point-n-shoot or DSLR camera, use this command
to adjust the time skew in EXIF tags and the file's modification timestamp (mtime):

$ exiftool "-alldates-=00:09:36" "-SonyDateTime-=00:09:36" "-FileModifyDate-=00:09:36" -overwrite_original DSC03485.JPG

alldates, as stated in the docs, "AllDates is a shortcut for 3 tag names: DateTimeOriginal, CreateDate and ModifyDate"
also, I here change the Sony specific Sony Date Time.

Also note that I don't use something like "-FileModifyDate<DateTimeOriginal" as that would set the file's timestamp to the tag value we'd just changed. The -overwrite_original flag tells exiftool to not create a backup copy of the untampered file,
as I simply copied the whole directory for backup prior to time adjustment.

Another example, this time on a Canon DSLR:

$ exiftool "-alldates+=01:00:19" "-FileModifyDate+=01:00:19" -overwrite_original IMG_5414.JPG

A related command/task is to rename files so that their name reflects their timestamp, instead of the generic IMG_ or DSC_ plus ascending number names. Sadly, it is not possible to have exiftool adjust skewed time/date timestamps and rename files to resulting timestamps in one go. This is because all setting is based on the values exiftool read out when the file is first opened, and it won't fill in values it has just changed (see above).
So something like this:

$ exiftool "-alldates+=01:00:19" "-FileModifyDate+=01:00:19" '-FileName<${FileModifyDate}_Canon.jpg' -d %Y_%m_%d_%H_%M_%S -overwrite_original IMG_5414.JPG

would result in renaming the files to the timestamp value *before* the adjustment. So we'll have to make the file renaming a separate task and

$ exiftool '-FileName<${FileModifyDate}_Canon.jpg' -d %Y_%m_%d_%H_%M_%S -overwrite_original IMG_5414.JPG

after we changed what *in* the file, after adjusting EXIF metadata. Important hint: Note the *single quotes* above, the variable placeholder won't work if you enclose the tag rule in double quotes.

My specific use case:

I had a whole folder of files with skewed timestamps. Also I wanted to interweave files I took with multiple cameras, unifying the stream of photos into
a directory of consistently named files. from what I had tested, I had to use a multi-step process to achieve that:

At first, I processed a folder of Canon files, and adjusted EXIF timestamps like so:

$ exiftool "-alldates+=01:00:19" -overwrite_original Photos_Canon/*

As you can see I adjusted EXIF tags only first. That is because I've noticed that file mtime timestamps are off from what's in the EXIF tags quite frequently - possibly because there's a time offset between preparing the file and the system writing it to the CF card. It's, if at all, only one or two seconds but for my use case here that's crucial. So I didn't use something like "-FileModifyDate+=01:00:19" as proposed above, but a separate command which read the file timestamp value from the EXIF tag:

$ exiftool "-FileModifyDate<DateTimeOriginal" -overwrite_original Photos_Canon/*

After that EXIF tags timestamps and filesystem timestamps were perfectly in line. Next up was renaming. But I wanted to preserve how the files were originally named, you know, this IMG_5123.JPG stuff Canon DSLRs write. It's a generic number and overly pedantic wanting to preserve it, but I wanted to have that stored in case I wanted to know how the file was originally named. So I ran a custom Perl tool which wrote the original filename, something like IMG_5125.JPG into the file's extended attributes.

After that I used exiftool again, this time to rename the files according to my timestamp based template, <YYYYMMDD>_<HHMMSS00>_Canon.jpg:

$ exiftool '-FileName<${DateTimeOriginal}00_Canon.jpg' -d %Y%m%d_%H%M%S -overwrite_original Photos_Canon/*

Two things to note here:

1. Interestingly enough, when writing EXIF tags, exiftool uses a temp file to make writing atomic and deal with errors. On renames
like here it doesn't - which is good (!) - as xattribs would be lost with a copy-on-write operation. (I might be wrong why it's like that, but anyway, exiftool does not interfere with xattribs here).

2. Note the trailing "00" after the time (HHMMSS) section? I use this additional variable because the rename resulted in a few errors, as some photos were taken during the very same second and exiftool refused to rename these when it created a duplicate. (Which, again, is good). These pictures in the very same second happen when a Sony point and shoot takes two pictures with slightly different exposure to compensate for difficult lighting conditions... So I run the rename twice, on pictures, with videos that's not an issue:

$ exiftool '-FileName<${DateTimeOriginal}01_Canon.jpg' -d %Y%m%d_%H%M%S -overwrite_original Photos_Canon/IMG*

Following that, I did the same for all directories containing photos from different cameras. So in summary, my specific workflow used as an example here, are these steps for a Sony camera:

$ exiftool "-alldates-=00:09:36" "-SonyDateTime-=00:09:36" -overwrite_original Photos_Sony/DSC*
$ exiftool "-FileModifyDate<DateTimeOriginal" -overwrite_original Photos_Sony/DSC*
$ [custom tool to store filenames in xattr]
$ exiftool '-FileName<${DateTimeOriginal}00_Sony.jpg' -d %Y%m%d_%H%M%S -overwrite_original Photos_Sony/DSC*
$ exiftool '-FileName<${DateTimeOriginal}01_Sony.jpg' -d %Y%m%d_%H%M%S -overwrite_original Photos_Sony/DSC*
$ exiftool "-FileModifyDate-=00:09:36" -overwrite_original Photos_Sony/MAH*
$ exiftool '-FileName<${FileModifyDate}_Sony.mp4' -d %Y%m%d_%H%M%S -overwrite_original Photos_Sony/MAH*

The last two steps you see above were to handle Sony video files a bit differently while they resided in that same directory. MP4s don't contain EXIF tags, so we use the File mtime here, first removed the time skew, then moved the date/time into the filename.

Voila! After all that, I could combine all files into one directory which now contains a unified photo stream.

Leave a Reply