#!/usr/bin/perl -w # # based on... # http://www.alumni.caltech.edu/~copeland/work/pix.html ## rename Exif files from digital camera ## based on the date and time the picture ## was taken use POSIX; use strict; sub usage { die "Usage: $0 [files...]\n"; } # Extract the photo time, and rename the file # based on that time. sub rename_picture { my $name = $_; # --- get the date using exiftool ... die "$name - not a .jpg, .jpeg, or .nef file\n" unless $name =~ m/\.(jpe?g|nef)$/i; my $ex = $1; $ex =~ tr/A-Z/a-z/; $ex =~ s/jpeg/jpg/; my $ptime = `exiftool -DateTimeOriginal "$name" | cut -d : -f 2-`; # --- try exiftags if that does not work ... if (not length($ptime)) { die "$name - not a .jpg or .jpeg file\n" unless $name =~ m/\.jpe?g$/i; $ptime = `exiftags -i "$name" | grep '^Image Created' | cut -d : -f 2-`; } # --- try a binery search if that does not work... if (not length($ptime)) { $ptime = `strings "$name" | grep '20[0-9][0-9]:[0-9][0-9]:[0-9][0-9] *[0-9][0-9]:[0-9][0-9]:[0-9][0-9]' | head -n1`; }; # --- assume we have a date now... # cleanup chomp $ptime; $ptime =~ s/^\s+//; # now that we've got the timestamp, # such as 1969:07:21 00:15:23", # we need to extract the components my $re = "(\\d\\d\\d\\d):(\\d\\d):(\\d\\d) " . "(\\d\\d):(\\d\\d):(\\d\\d)"; die "bad date format in $_" unless $ptime =~ /$re/o; my $fdate = $1 . $2 . $3; my $ftime = $4 . $5 . $6; my $newname = $fdate . "-" . $ftime . ".$ex"; my $ctime = mktime($6, $5, $4, $3, $2 - 1, $1 - 1900, 0, 0, 1); if( $name eq $newname ) { warn $newname . " already valid name, skipping.\n"; return; } if( -r $newname ) { warn $newname . " already exists, appending original file name\n"; $newname = $fdate . "-" . $ftime . "-" . $name; # lower case it $newname =~ tr/A-Z/a-z/; } if( -r $newname ) { warn "file $newname already exists"; return; } rename $name, $newname or die "can't rename $name to $newname"; print "rename $name, $newname\n"; # now re-time the file, too utime $ctime, $ctime, $newname; } ### main program if( @ARGV ) { for( @ARGV ) { rename_picture($_); } } else { usage(); }