Introduction
At least once a year we go for holiday together with some friends. No question, they all bring their digital cameras and take a load of pictures.
Right after we get back home they send me their images to upload them to our gallery.
The Problem
Then i usually end up with a directory structure looking smthg like:
.
├── philipp
│ └── S8000
│ ├── DSC_0700.JPG
│ ├── DSC_0701.JPG
│ └── DSC_0709.JPG
├── iris
│ ├── C5600
│ │ ├── DSCN4664.JPG
│ │ ├── DSCN4666.JPG
│ │ └── DSCN4667.JPG
│ └── D80
│ ├── DSC_0830.JPG
│ ├── DSC_0837.JPG
│ ├── DSC_0838.JPG
│ └── DSC_0839.JPG
├── nina
│ └── S3000
│ ├── DSCN4610.JPG
│ ├── DSCN4616.JPG
{{- $pages = where site.RegularPages "Type" "in" site.Params.mainSections }}
│ └── DSCN4617.JPG
└── tom
├── D70
│ ├── DSC_4040.JPG
│ ├── DSC_4048.JPG
│ └── DSC_4049.JPG
└── iphone
├── IMG_0104.JPG
└── IMG_0105.JPG
First of all, there might be duplicate filenames as in the example above. But the major problem is that these photos are not sorted by the date they'd been taken which makes it hard to just browse them all and sort out the ones we dislike.
The Script
This is far from being perfect. Actually it's just a quick hack, but it does the job for me.
It sorts all images given according to its EXIF CreateDate, copies/moves the files and prefixes them with an incrementing number.
Prerequisites:
- Image::Exiftool
#!/usr/bin/perl -w
##################################################
#Move or copy images and rename them to be sorted by EXIF-CreateDate
#cmdline options:
#./cmd -move
#./cmd -copy -dest
##################################################
use strict;
use Image::ExifTool;
use Time::Local;
use Getopt::Long;
use File::Basename;
use File::Copy;
our $dest;
our $copy;
our $move;
my %Info;
GetOptions ('dest=s' => \$dest,
'copy' => \$copy,
'move' => \$move
);
foreach (@ARGV) {
GetDateAndTime($_, \%Info);
}
SortAndMove(\%Info);
sub GetDateAndTime {
my ($srcfile, $Info_ref) = @_;
my $srcfileExif = new Image::ExifTool;
my $info = $srcfileExif->ImageInfo($srcfile,"CreateDate");
$$info{'CreateDate'} =~ s/\s+/:/g;
my ($year,$mon,$mday,$hour,$min,$sec) = split(/:/, $$info{'CreateDate'});
$mon = $mon-1;
$$Info_ref{$srcfile} = timelocal($sec,$min,$hour,$mday,$mon,$year);
}
sub SortAndMove {
my ($Info_ref) = @_;
my $count = sprintf("%0".length(keys %$Info_ref)."d",0);
foreach (sort {$$Info_ref{$a} cmp $$Info_ref{$b}} keys %$Info_ref) {
move("$_",dirname($_) . "/" . $count . "_" . basename($_)) if $move;
copy("$_",$dest . "/" . $count . "_" . basename($_)) if $copy;
$count++;
}
}
Tested on:
- ArchLinux
- Debian GNU/Linux Squeeze
Cameras tested with:
- Nikon D70s
- Nikon D80
- Nikon Coolpix 5600
- Apple Iphone 3GS
Example 1: Sort on Copy
Input Filenames: $ find a/ -xdev -iname "*.jpg*"
a/iris/D80/DSC_0838.JPG
a/iris/C5600/DSCN4665.JPG
a/philipp/S8000/DSC_0700.JPG
a/philipp/S8000/DSC_0705.JPG
a/nina/S3000/DSCN4613.JPG
a/nina/S3000/DSCN4614.JPG
a/tom/iphone/IMG_0102.JPG
a/tom/D70/DSC_4043.JPG
a/tom/D70/DSC_4048.JPG
Copy and sort: $ NameByExifDate.pl -c -d b/ `find a/ -xdev -iname "*jpg*"`
Resulting Filenames: $ find b/ -xdev -iname "*.jpg*"
b/0_DSC_0700.JPG
b/1_DSCN4613.JPG
b/2_DSCN4614.JPG
b/3_DSC_0705.JPG
b/4_IMG_0102.JPG
b/5_DSCN4665.JPG
b/6_DSC_0838.JPG
b/7_DSC_4043.JPG
b/8_DSC_4048.JPG
Example 2: Sort on Move
*Input Filenames: $ find a/ -xdev -iname "*.jpg*"
a/iris/D80/DSC_0838.JPG
a/iris/C5600/DSCN4665.JPG
a/philipp/S8000/DSC_0700.JPG
a/philipp/S8000/DSC_0705.JPG
a/nina/S3000/DSCN4613.JPG
a/nina/S3000/DSCN4614.JPG
a/tom/iphone/IMG_0102.JPG
a/tom/D70/DSC_4043.JPG
a/tom/D70/DSC_4048.JPG
Move and sort: $ NameByExifDate.pl -m `find a/ -xdev -iname "*jpg*"`
Resulting Filenames: $ find a/ -xdev -iname "*.jpg*"
a/iris/D80/6_DSC_0838.JPG
a/iris/C5600/5_DSCN4665.JPG
a/philipp/S8000/0_DSC_0700.JPG
a/philipp/S8000/3_DSC_0705.JPG
a/nina/S3000/1_DSCN4613.JPG
a/nina/S3000/2_DSCN4614.JPG
a/tom/iphone/4_IMG_0102.JPG
a/tom/D70/7_DSC_4043.JPG
a/tom/D70/8_DSC_4048.JPG
The sort on move routine preserves the original directory structure while the sort on copy routine flattens the hierarchy to a single destination directory.
I highly appreciate feedback of any kind.