#! /usr/bin/perl # copyphotos.pl - transfers images from camera or memory card, # renaming files based on timestamp or EXIF data # # Usage: copyphotos.pl # # Written by Jon Allen # http://perl.jonallen.info/projects/phototools #--Load required modules and activate Perl's safety features--------------- use strict; use warnings; use English; use Data::Dumper; use File::Copy; use File::Find; use File::Path; use File::Spec::Functions qw/catfile catdir/; use POSIX qw/strftime/; use Time::localtime; our $VERSION = '0.04'; #--Check command-line options---------------------------------------------- my $usage = "Usage: $0 "; my $source_dir = $ARGV[0] or die "$usage\n"; my $destination_dir = $ARGV[1] or die "$usage\n"; #--Try to load the Image::ExifTool module---------------------------------- eval qq{ use Image::ExifTool; }; if ($EVAL_ERROR) { warn("[Warning] Image::ExifTool not installed, using file modification for timestamp\n"); } #--Specify relevant file extensions---------------------------------------- my $extensions = join '|',qw/ JPG JPE JPEG TIF TIFF /; #--Search for image files-------------------------------------------------- my @file_list; find({ wanted => sub { if (/\.$extensions$/i) { push @file_list,$File::Find::name; } }, no_chdir => 1 }, $source_dir); #--Copy and rename files--------------------------------------------------- foreach my $file (@file_list) { copy_rename(source => $file, destination => $destination_dir,); } exit(0); #-------------------------------------------------------------------------- #-------------------------------------------------------------------------- sub copy_rename { my %args = @_; # Get timestamp of source file my ($year,$month,$day,$hour,$minute,$second) = get_timestamp(filename => $args{source}); # Create target directory path (../year/month/day/..files..) my $target_directory = catdir($args{destination}, sprintf("%04.4s",$year), sprintf("%02.2s",$month), sprintf("%02.2s",$day)); unless (-d $target_directory) { eval { mkpath($target_directory); }; if ($EVAL_ERROR) { die ("Could not create directory $target_directory: $@"); } } # Define destination file name my $timestamp = sprintf("%04.4s-%02.2s-%02.2s_%02.2s-%02.2s-%02.2s", $year,$month,$day,$hour,$minute,$second); my $extension = ($args{source} =~ /\.(\w+)$/) ? $1 : ''; my $destination = catfile($target_directory,"$timestamp.$extension"); # If destination file exists, append sequence number to filename if (-e $destination) { my $suffix = 0; do { $suffix++; $destination = catfile($target_directory,$timestamp.'_'."$suffix.$extension"); } while (-e $destination); } # Print status message and copy file { local $OUTPUT_AUTOFLUSH = 1; print "Copying $args{source} to $destination ... "; } if (copy($args{source},$destination)) { print "OK\n"; } else { print "FAILED: $!\n"; } } #-------------------------------------------------------------------------- sub get_timestamp { my %args = @_; if (exists $INC{'Image/ExifTool.pm'}) { my $exifinfo = Image::ExifTool->new->ImageInfo( $args{filename}, 'DateTime', 'DateTimeOriginal', {DateFormat=>'%Y:%m:%d:%H:%M:%S'} ); if (my $timestamp = $exifinfo->{DateTime} || $exifinfo->{DateTimeOriginal}) { return split /:/,$timestamp; } } my $mtime = (stat($args{filename}))[9]; my $year = localtime($mtime)->year + 1900; my $month = localtime($mtime)->mon +1; my $day = localtime($mtime)->mday; my $hour = localtime($mtime)->hour; my $minute = localtime($mtime)->min; my $second = localtime($mtime)->sec; return ($year,$month,$day,$hour,$minute,$second); } #-------------------------------------------------------------------------- sub _MANIFEST { require 'Image/ExifTool.pm'; require 'Image/ExifTool/Exif.pm'; require 'Image/ExifTool/Shortcuts.pm'; require 'Image/ExifTool/PrintIM.pm'; require 'Image/ExifTool/Canon.pm'; require 'Image/ExifTool/Nikon.pm'; require 'Image/ExifTool/Olympus.pm'; require 'Image/ExifTool/Casio.pm'; require 'Image/ExifTool/Kodak.pm'; require 'Image/ExifTool/Minolta.pm'; require 'Image/ExifTool/MakerNotes.pm'; require 'Image/ExifTool/FujiFilm.pm'; require 'Image/ExifTool/Sony.pm'; require 'Image/ExifTool/Pentax.pm'; require 'Image/ExifTool/Sigma.pm'; require 'Image/ExifTool/Ricoh.pm'; require 'Image/ExifTool/Sanyo.pm'; require 'Image/ExifTool/Panasonic.pm'; require 'Image/ExifTool/JVC.pm'; require 'Image/ExifTool/Leaf.pm'; }