use POSIX qw(strftime);
use File::Copy;
use File::Path qw(make_path);
-use File::Basename;
+use File::Basename qw(dirname basename);
use Date::Parse qw(str2time);
+use IPC::System::Simple qw(capturex);
+use Digest::SHA qw(sha256_hex);
my %options = (debug => 0,
help => 0,
# find already existing files
my %existing_files;
-find(sub { if (-f $_) {$existing_files{$_} = $File::Find::name;} },$options{archive_dir});
+find(sub { if (-f $_ or -l $_) {$existing_files{$_} = $File::Find::name;} },$options{archive_dir});
for my $file (@files) {
my $file_basename=basename($file);
next;
}
my $epoch = str2time($info->{CreateDate});
- my $dir = strftime('%Y/%m_%B/%Y_%m_%d/',localtime($epoch)).'orig/';
+ my $dir = strftime('%Y/%m_%B/%Y_%m_%d/',localtime($epoch));
if (not -d $options{archive_dir}.'/'.$dir) {
make_path($options{archive_dir}.'/'.$dir) or
die "Unable to make dir $!";
my $end_location = $options{archive_dir}.'/'.$dir.$file_basename;
if (-e $end_location) {
print STDERR "$file already exists in $end_location\n";
- } elsif (exists $existing_files{$file_basename}) {
+ } elsif (exists $existing_files{$file_basename} and
+ are_the_same_files({name => $existing_files{$file_basename}},
+ {name => $file, info => $info})) {
print STDERR "$file already exists in $existing_files{$file_basename}\n";
} else {
print STDERR "copying $file to $end_location\n";
}
}
+# return true if the files are close enough that we should consider it
+# the same picture
+sub are_the_same_files{
+ my ($f1,$f2) = @_;
+ # load the exif information if we can
+ for my $f (@_) {
+ if (-e $f->{name}) {
+ $f->{exists} = 1;
+ if (not exists $f->{info} or not defined $f->{info}) {
+ $f->{info} = ImageInfo($f->{name});
+ }
+ } else {
+ $f->{exists} = 0;
+ }
+ }
+ # if the files both exist, compare some exif information
+ if (defined $f1->{info} and $f2->{info}) {
+ if ($f1->{info}{CreateDate} eq $f2->{info}{CreateDate} and
+ $f1->{info}{Serial} eq $f2->{info}{Serial}
+ ) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ # ok; can't compare exif. Compare sha256 sums
+ for my $f (@_) {
+ if (-l $f->{name}) {
+ # this is probably a git annex file
+ $f->{sha256} = git_annex_sha256($f->{name});
+ } elsif (-e $f->{name}) {
+ $f->{sha256} = calc_sha256($f->{name})
+ }
+ }
+ # if the sha256 are equal, they're the same. if not, or if we
+ # can't compare, assume they're different.
+ if (defined $f1->{sha256} and
+ defined $f2->{sha256} and
+ $f1->{sha256} eq $f2->{sha256}
+ ) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+sub calc_sha256{
+ my ($fn) = @_;
+
+ my $sha = Digest::SHA->new(256);
+ $sha->addfile($fn);
+ return($sha->hexdigest());
+}
+
+sub git_annex_sha256 {
+ my ($fn) = @_;
+ my $info = capturex('git','-C',dirname($fn),'annex','info',basename($fn));
+ my ($sha256) = $info =~ /key:.+SHA256E-[^-]+--([^\.]+)/;
+ return $sha256;
+}
+
__END__