Reading and Changing Exif Photo Times with PowerShell

(Part 1 of 3) (Part 2) (Part 3)

{Updated: 08/2013}

Back in 2011 I went off with a bunch of like-minded folk on a long-distance cycle (see, for example, here).  We all had a great time, but with six separate cameras in use we came back with a whole load of photos that needed sorting out.

We wanted to combine all the photos from the trip into a single consolidated collection, but apart from renaming all the image files it was also going to be necessary to change the times (the Date Taken values) so the photos all appeared in the correct order when viewed.

Rather than trying to accurately synchronise the times on all of cameras, we used a simple trick of simultaneously pointing them all at a scene and taking a common image; this would allow us to later correct the times of each image to at least the nearest second.  (See below for the actual photos!)

The obvious question is then how to actually change the times and rename the files?  Well, there are countless photo programs (e.g. Windows Live Photo Gallery, Picassa, etc, etc) that would do this, but for batch updates it’s a lot easier to use PowerShell.

Here’s how to rename the files:

$FormStr=”LeJog 2011 {0:MM-dd dddd} ({1}).jpg”
gci *.jpg | Get-ExifDateTaken | Ren -New {$FormStr -f $_.ExifDateTaken,(Split-Path (Split-Path $_) -Leaf)}

There are a couple of things to notice here…. Firstly, the new file name is specified in a scriptblock, this returns a dynamically calculated file name based on the original PathInfo item that was passed to the Rename cmdlet (in the $_ variable) and the time the photo was taken (passed in $_.ExifDateTaken).

The PowerShell format operator (-f) combines the template string, in the $FormStr variable, with the values necessary to calculate the new name. In this case, the photos from each camera were held in a folder named for the camera’s owner (so my photos were all in ..\Chris\img001.jpg … etc); so ‘Split-Path (Split-Path $_) –Leaf’ just returns the parent folder names – in this case, ‘Chris’, ‘David’, ‘Mick’, ‘Mike’ or ‘Andy’ [name plugs].

The date-time part of the name just uses standard DateTime format strings, so the resulting renamed image might be something like:

“LeJog 2011 07-10 14.27.21 Sunday (Chris).jpg”

…the important point here is that you can create any name you want; you might not like my choice of filename (although it is at least sortable!) but flexibility is unlimited here.

The other thing to notice is the Get-ExifDateTaken cmdlet.  The source for this, along with the  companion Update-ExifDateTaken cmdlet will be published in a the next two blog entries (Part 2) (Part 3).

The example above shows how to rename a bunch of image files.  To actually change the Date Taken value needs a different approach.  Photos store meta-data such as the Date Taken value as Exif information which is actually combined with the image data within the image file, so the image file must be opened and saved to modify the Date Taken Exif value.  The Update-ExifDateTaken script cmdlet does this:

gci *.jpg | Update-ExifDateTaken -Offset ‘-0:07:10’ -PassThru | ft Path, ExifDateTaken

Here, we specify the amount of time the Date Taken value on each image file should be changed by.  In the example the offset is negative, so any Date Taken values will be moved forwards to earlier times (presumably this particular camera’s clock was too fast).

Note that this technique can also be useful if you go across time zones and forget to change your camera’s clock…

Finally, here’s an example that shows how to modify the Exif Date Taken meta-data and rename the image file in the same command:

$FormStr=”LeJog 2011 {0:MM-dd dddd} ({1}).jpg”
gci *.jpg | Update-ExifDateTaken -Offset ‘-0:07:10’ -PassThru |
Ren -New {$FormStr -f $_.ExifDateTaken,(Split-Path (Split-Path $_) -Leaf)}

The Get-ExifDateTaken and the Update-ExifDateTaken script cmdlets were written with input from James O’Neill’s session at the 2011 European PowerShell Deep Dive event in Frankfurt; James has written-up the session in a blog here: “Maximize the reuse of your PowerShell”.

The script cmdlets will be published in the follow-up blog entries: (Part 2) (Part 3)

Oh, and the image we used to sync the camera times?  Here’s one of our tireless support drivers, Andy, holding up the lunchtime sausage:

LeJog 2011 07-06 14.13.54 Wednesday (Andy) LeJog 2011 07-06 14.13.54 Wednesday (Chris) LeJog 2011 07-06 14.13.54 Wednesday (David)
LeJog 2011 07-06 14.13.54 Wednesday (Mick) (2) LeJog 2011 07-06 14.13.54 Wednesday (Mick) LeJog 2011 07-06 14.13.54 Wednesday (Mike)

3 thoughts on “Reading and Changing Exif Photo Times with PowerShell”

  1. Thanks for the plug. I’ve done stuff with exif as well – commonly syncing information from my scuba “computer” – the watch which logs information about the dive – to my photos, I’ve found I photograph the dive computer showing the time (or a GPS unit showing the time when I’m logging GPS data) and then I’ve something with camera-time and what_I_am_syncing_with-time in one place. Never had to photograph the clock on another camera though :-)

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s