Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Change Image File Timestamp to Match EXIF Data

by shoness (Friar)
on Jun 01, 2009 at 07:10 UTC ( #767176=snippet: print w/ replies, xml ) Need Help??

Description: I catalog images by the date each was taken. My camera timestamps its images with the date/time. Perfect!

However, when I later "modify" an image, or when I transfer it over BlueTooth, etc. the "Date Modified" for the file changes.

I use this little script to change the atime/mtime for the image file BACK to where it should be.

All the action is inside Image::ExifTool, nevertheless, I welcome your feedback!

UPDATE: Added error checking.

#!/usr/bin/perl
use warnings;
use strict;
use Time::Local;
use Image::ExifTool qw(:Public);

my $exifTool = new Image::ExifTool;

foreach my $file (@ARGV) {

  # Read only the "DateTimeOriginal" tag from the file.
  my $info = $exifTool->ImageInfo($file, 'DateTimeOriginal');

  # Error Handling
  if (defined $exifTool->GetValue('Error')) {
    print "ERROR: Skipping '$file': " . $exifTool->GetValue('Error') .
+ "\n";
    next;
  }
  if (not exists $info->{'DateTimeOriginal'}) {
    warn "File '$file' has no EXIF 'DateTimeOriginal' tag. Skipping it
+.\n";
    next;
  }
  if (defined $exifTool->GetValue('Warning')) {  # Can there be a warn
+ing?
    print "Warn: Processing '$file': " . $exifTool->GetValue('Warning'
+) . "\n";
  }
  # I suppose we could still check to make sure the data is "reasonabl
+e".
  # There could be garbage data in the DateTimeOriginal field and we'd
+ be
  # in trouble...

  # Our data comes in the form "YEAR:MON:DAY HOUR:MIN:SEC".
  # utime() wants data in the exact opposite order, so we reverse().
  my @date = reverse(split(/[: ]/, $info->{'DateTimeOriginal'}));

  # Note that the month numbers must be shifted: Jan = 0, Feb = 1
  --$date[4];

  # Convert to epoch time format
  my $time = timelocal(@date);

  # Make the change to the mtime and atime
  my $status = utime($time, $time, $file);
  if ($status != 1) {
    print "Warn: utime() on '$file' returned $status instead of 1.\n";
  }
}

__END__

=head1 SYNOPSYS

  Reads the "DateTimeOriginal" EXIF field out of an image file
  and changes the "last accessed time" and "last modified time"
  of the file to match it.

=head1 USAGE

  On Unix:
    thisfile.pl *.jpg another/dir/*.jpg

  On Windows:
    perl thisfile.pl bunch.jpg of.jpg files.jpg

  Everything you give to this file is expected to be a filename.
  It accepts no other switches or arguments.

=cut
Comment on Change Image File Timestamp to Match EXIF Data
Download Code
Re: Change Image File Timestamp to Match EXIF Data
by Paladin (Priest) on Jun 01, 2009 at 08:56 UTC
    Cool utility. A small suggestion for the next version: Instead of die()ing if it can't read a file, perhaps just warn() and skip to the next file so the rest still get processed.
      Does the -r file test guarantee that ImageInfo will be successful? I wonder if it would be better to omit the file test, then analyze the return status of ImageInfo to determine whether to proceed with processing. Of course, ImageInfo might just die anyway, in which case an eval might be useful to capture the failure.
Re: Change Image File Timestamp to Match EXIF Data
by Limbic~Region (Chancellor) on Jun 01, 2009 at 14:05 UTC
    shoness,
    I catalog images by the date each was taken.

    I do too. It really sucks when the camera has the wrong date time stamp. In that case, it the EXIF data you need to modify - see (Solved) Change "Date Picture Taken" with Image::ExifTool.

    I would recommend checking the return of utime since it may fail. I also agree with the other comment that perhaps you want to warn and not die. You might also want to consider not updating the time stamp unless it is different.

    I am kind of interested in what tool you use to organize your pictures that depends on the timestamp of the file and not the internal Exif data. I personally have written my own tools but I completely ignore the file time stamp and don't run into the problem you are having.

    Cheers - L~R

Re: Change Image File Timestamp to Match EXIF Data
by jasonk (Parson) on Jun 02, 2009 at 00:53 UTC

    Beware that messing with utime can have drastic consequences. A prime example would be that most backup software is not going to be backing up your changed files, since you're lying about when they were last changed, tricking it in to thinking there were no changes...


    www.jasonkohles.com
    We're not surrounded, we're in a target-rich environment!
Re: Change Image File Timestamp to Match EXIF Data
by Anonymous Monk on Aug 10, 2009 at 22:45 UTC

    Nifty tool, I was going to write one myself, but a quick search found this.

    I ran this on a copied subtree of photos of my young daughter - I wrote a perl script to extract all my files from flickr as I'm making my own gallery now.

    This script complained a lot with warnings, but it did do exactly what I needed first go to all images that had Exif data (I processed some wayback before I knew to preserve the exif data in gimp).

    I would call it quick and dirty, its exactly what perl does best.

Re: Change Image File Timestamp to Match EXIF Data
by merlyn (Sage) on Aug 10, 2009 at 23:40 UTC
    Neat. Mine looked like this:
    #!/usr/bin/env perl use strict; $|++; use Image::ExifTool qw(ImageInfo); use Time::Local; for my $file (@ARGV) { my $ii = ImageInfo($file, qw(DateTimeOriginal DateTime)) or warn("Skipping $file\n"), next; my ($created) = grep /\S/, @$ii{qw(DateTimeOriginal DateTime)}; next unless $created; warn "using $created for $file\n"; if ($created =~ s/([-+ ])(\d\d):(\d\d)$//) { my ($sign, $hour, $minute) = ($1, $2, $3); # warn "ignoring offset of $sign $hour:$minute\n"; } my @digits = $created =~ /(\d+)/g or next; if ($digits[0] < 1900) { warn "bad year $digits[0] for $file"; next; } $digits[0] -= 1900; $digits[1] -= 1; my $gmtime = timegm(reverse @digits); if ($gmtime > time or $gmtime < time - 86400*90) { warn "preposterous gmtime for $file: ", scalar gmtime $gmtime; # next; } utime($gmtime, $gmtime, $file) or warn "Cannot utime on $file: $!"; }

    -- Randal L. Schwartz, Perl hacker

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

Re: Change Image File Timestamp to Match EXIF Data
by Anonymous Monk on Aug 11, 2009 at 08:46 UTC

    I used few days ago something like ...

    # arw: Sony raw file suffix. for f in *.arw *.jpg do exiftool -S -d "%Y%m%d%H%M.%S" -CreateDate "${f}" \ | awk '{ print $2 }' \ | xargs -I % touch -m -t % "${f}" done

Back to Snippets Section

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: snippet [id://767176]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (15)
As of 2014-10-23 14:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (125 votes), past polls