I’ve taken a few quick adhoc backups in the past, copying whole directories of image files onto the server with a view to “sorting out that lot later..“.  Having an almost full file system, new disc drives at a premium and being rationed, that time is now!

I’d written a tool with Phil Harvey’s Perl module Image::ExifTool in the past to rename files from the camera format IMG_<num>.CR2 to YYYYMMDD-HHMMSS-IMG_<num>.CR2 to avoid clashes with file names. So I knew I had a module at hand to help, only this time I’d just be reading the date from the files.  Thanks to Lightrooms export function keeping that same shoot date in the JPEGs, the code would match CR2, DNG and JPEGS.

With high speed shutter mode grouping files just by date wasn’t enough, so I also pulled the last set of digits from the file name and used them in the grouping.  The code runs on Windows with Active State Perl as well as Linux. I suspect MacOS X would be fine too. Each just needs the correct file system starting point in the find() function.  The result is lines of output like this:

20120114-225537 2400 C:/Users/emerym/Pictures/Catalogued in Lightroom/Birthday Parties/2012-01-14/IMG_2400.DNG
20120114-225537 2400 C:/Users/emerym/Desktop/Lightroom Export/Mike/IMG_2400.JPG
20120129-154305 2514 C:/Users/emerym/Pictures/Catalogued in Lightroom/Studio and Location Shoots/2012/2012-01-29/Three Qtr/IMG_2514.DNG
20120129-154305 2514 C:/Users/emerym/Desktop/Lightroom Export/Lydia/FACEBOOK/IMG_2514.JPG
20120129-182307 2599 C:/Users/emerym/Pictures/Catalogued in Lightroom/Studio and Location Shoots/2012/Sophie/IMG_2599.DNG
20120129-182307 2599 C:/Users/emerym/Pictures/iPhone/Family & Friends/IMG_2599.JPG

The source code:

#!/usr/bin/perl -w

use File::Spec;
use Image::ExifTool;
use Data::Dumper;
use File::Find;

find(\&Wanted, "/opt/photos/");

foreach $date (sort keys %data) {
        foreach $num (sort keys %{$data{$date}}) {
                @files=keys %{$data{$date}{$num}};
                if ($files>1) {
                        foreach $file (@files) {
                                print $date. " " . $num . " " .$file . "\n";

sub Wanted {
        # Only operate on my image files!
        (/(\d+)\.CR2$/i | /(\d+)\.JPG$/i | /(\d+)\.DNG$/i) or return;
        my $num=$1;
        my $path = $File::Find::dir . "/" . $_;
        print STDERR $path . "\n";
        # Get date and time from EXIF data.
        my $exif = new Image::ExifTool;
        $exif->Options(DateFormat => "%Y%m%d-%H%M%S");
        my @ioTagList = ("DateTimeOriginal");
        my $info = $exif->ImageInfo($path, @ioTagList);
        my $datetime = $$info{"DateTimeOriginal"};