]> mj.ucw.cz Git - gallery.git/blob - bin/gal-date
451201cec3e11f5a61d866a9e06711100208a1e5
[gallery.git] / bin / gal-date
1 #!/usr/bin/perl
2 # UCW Gallery: Symlink photos according to their EXIF timestamps
3 # (c) 2013 Martin Mares <mj@ucw.cz>
4
5 use strict;
6 use warnings;
7
8 use Image::EXIF;
9 use Getopt::Long;
10
11 if (@ARGV && $ARGV[0] eq '--help') {
12         die <<AMEN ;
13 Usage:  cat list | gal date [<options>]
14    or:  gal date [<options>] <files>
15
16 Options:
17 -d, --destdir=<dir>     Create symlinks in specified directory (default: current dir)
18 -n, --dry-run           Perform a trial run with no changes made
19 -o, --offset=<offset>   Adjust timestamps by a given offset (<h>[:<m>[:<s>]])
20     --suffix=<s>        Add suffix to all names
21 -s, --symbolic          Create symbolic links (default: hardlinks)
22 AMEN
23 }
24
25 my $destdir = '.';
26 my $dry_run = 0;
27 my $offset = 0;
28 my $suffix = "";
29 my $symbolic = 0;
30 Getopt::Long::Configure('bundling');
31 GetOptions(
32         'destdir|d=s' => \$destdir,
33         'dry-run|n!' => \$dry_run,
34         'offset|o=s' => \$offset,
35         'suffix=s' => \$suffix,
36         'symbolic|s!' => \$symbolic,
37 ) or die "Try gal date --help\n";
38
39 my @src = @ARGV;
40 if (!@src) {
41         while (<STDIN>) {
42                 chomp;
43                 push @src, $_;
44         }
45 }
46
47 if ($offset =~ m{^([+-])?(\d)+(:(\d+)(:(\d+))?)?$}) {
48         $offset = $2 * 3600 + ($4 // 0) * 60 + ($6 // 0);
49         if ($1 eq '-') { $offset = -$offset; }
50 } else {
51         die "Invalid offset: $offset\n";
52 }
53
54 foreach my $f (@src) {
55         my $e = new Image::EXIF($f);
56         my $i = $e->get_all_info();
57         if ($e->error) {
58                 print STDERR "EXIF error on $f: ", $e->error, "\n";
59                 next;
60         }
61         # print STDERR Dumper($i), "\n";
62
63         my $d = $i->{'image'}->{'Image Created'};
64         if (!defined $d) {
65                 print STDERR "No date for $f\n";
66                 next;
67         }
68         my ($ty, $tm, $td, $tH, $tM, $tS) = ($d =~ m{^(\d{4}):(\d{2}):(\d{2}) (\d{2}):(\d{2}):(\d{2})$}) or die "EXIF date parse error: $d\n";
69         my $t = 3600*$tH + 60*$tM + $tS;
70         $t = int($t + $offset);
71         $tH = int($t / 3600);
72         $tM = int(($t % 3600) / 60);
73         $tS = $t % 60;
74
75         my $retry = 0;
76         my $dest = "";
77         do {
78                 $dest = sprintf("%s/%04d-%02d-%02d-%02d:%02d:%02d%s%s.jpg",
79                         $destdir,
80                         $ty, $tm, $td,
81                         $tH, $tM, $tS,
82                         $suffix,
83                         $retry ? sprintf("-%d", $retry) : "");
84                 $retry++;
85         } while (-f $dest);
86
87         print "$f $dest\n";
88
89         unless ($dry_run) {
90                 if ($symbolic) {
91                         symlink $f, $dest or die "Cannot symlink $f to $dest: $!\n";
92                 } else {
93                         link $f, $dest or die "Cannot hardlink $f to $dest: $!\n";
94                 }
95         }
96 }
97
98 STDOUT->autoflush(1);