
So, I’m lazy. I also like things to work perfectly. This is why I write tools to do things so that I don’t have to. After recently moving to Linux for my main desktop, I wanted to be able to do everything I had previously done when it was running Windows, with a reasonable amount of effort. One thing I needed to be able to do is manage my photos. I was happy when I found out that Picasa runs just fine in Linux, so most of the battle is won. One of the things that always bugged me in Windows was transferring photos from removable media, such as an SD card. In my mind, this should be a simple process:
- Copy the photos to a specific location, with a folder named appropriately
- Skip duplicates
- Do all of this without having to do anything manually
I whipped up a script to do this very thing, in such a way that actually was easier and better than in Windows! I used perl for the job, and a CPAN module to get the file information. It’s super fast to boot. Here’s the code:
#!/usr/bin/perl
# Photo Importer
# Copies photos from removable media
# by Ed Salisbury (ed@edsalisbury.net)
# http://www.edsalisbury.net
# (c)2009 Ed Salisbury, Some Rights Reserved
#
# License:
# Except where otherwise noted, this work is licensed under Creative Commons
# Attribution ShareAlike 3.0.
#
# You are free:
# * to Share — to copy, distribute and transmit the work
# * to Remix — to adapt the work
#
# Under the following conditions:
# * Attribution. You must attribute the work in the manner specified by the
# author or licensor (but not in any way that suggests that they endorse
# you or your use of the work).
# * Share Alike. If you alter, transform, or build upon this work, you may
# distribute the resulting work only under the same, similar or ai
# compatible license.
# * For any reuse or distribution, you must make clear to others the license
# terms of this work. The best way to do this is with a link to the
# license's web page (http://creativecommons.org/licenses/by-sa/3.0/)
# * Any of the above conditions can be waived if you get permission from the
# copyright holder.
# * Nothing in this license impairs or restricts the author's moral rights.
# The location of your photos
my $DEST = "/data/photos/Our Family";
use warnings;
use strict;
use Image::ExifTool qw(:Public);
use Data::Dumper;
use File::Copy;
use File::Find;
# File::Find can spit out some warnings that we don't care about, so disable
no warnings 'File::Find';
# Turn off output buffering
$|++;
my $mounted = 0;
my $count = 0;
my $mnt = '';
print "Checking for media...";
while (!$mounted)
{
# I have Nikon and Canon cameras - change/add as needed
$mounted = `mount | egrep 'NIKON|CANON'`;
if (!$mounted)
{
# Look for a mounted device for 20 seconds
if ($count < 20)
{
print ".";
sleep(1);
$count++;
}
else
{
# Give up
print " not found.n";
exit();
}
}
else
{
# Found a device, get the directory it's mounted on
$mounted =~ /on (.*?) type/;
$mnt = $1;
print " found. ($mnt)n";
}
}
# Go through the mounted filesystems looking for files
find(&cp, $mnt);
sub cp
{
# Only copy jpegs - change if you use TIFs or RAW files
/.jpg$/i or return;
print "Copying file $_... ";
my $file = $_;
# Get the EXIF data from the file and extract the date
my $info = ImageInfo($File::Find::name);
my $date_time = $info->{'DateTimeOriginal'};
my @fields = split(":", $date_time);
my $year = $fields[0];
my $day = (split(" ", $fields[2]))[0];
my $date = $fields[0] . "_" . $fields[1] . "_" . $day;
# I use YEAR/MM_DD_YY for the dir name, feel free to change for your needs
my $dest_dir = "$DEST/$year/$date";
# Duplicate check
if (-f "$dest_dir/$file")
{
print "skipping.n";
return;
}
# Create the directory if needed
if (! -d "$dest_dir")
{
system("mkdir -p "$dest_dir"");
}
# Copy the file
if (copy($File::Find::name, "$dest_dir/$file"))
{
print "done.n";
}
else
{
# Something broke!
print "FAILED.n";
exit();
}
}
In order to run this script, you will need to install the Image::ExifTool module from CPAN (instructions)
A few things to pay attention to (and possibly change):
- The output directory ($DEST)
- The camera manufacturers it’s looking for
- The date format
To make this process even better, when you insert a media card, your OS will usually ask you what you want to do. If you have it run this script (every time), then it will automatically copy the files any time you stick a card in. This is the way I have mine set up, and I love it! Please let me know if you find this useful or have any improvement suggestions!