-
Notifications
You must be signed in to change notification settings - Fork 11
/
exif-search
executable file
·108 lines (81 loc) · 2.41 KB
/
exif-search
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#!/usr/bin/env perl
=head1 SYNOPSIS
C<exif-search> is a program that finds files with matching EXIF information.
Example: Find files store under 2 folders with Geo tags that is with 5kms from [Erlin Butokuden][1]
exif-search \
--ll 23.8997913,120.3691942 --disntance 5 \
/data/main/Pictures /data/backup/Pictures
[1]: https://goo.gl/maps/genakeXbVdaK8oDb7
=head1 OPTIONS
--ll lat,long -- that is, 2 decimals with a comma in between.
This is the usual format found in valious web-based maps.
--distance A decimal number in kilometres. The default is 10.
This option is only meaningful if C<--ll> is also given.
=cut
use v5.18;
use strict;
use warnings;
use Pod::Usage qw(pod2usage);
use GIS::Distance;
use File::Next;
use Getopt::Long;
use Image::ExifTool;
use Image::ExifTool::Location;
sub build_filter_camera {
my ($opts) = @_;
my $camera = lc($opts->{camera});
return sub {
my ($exif, $info) = @_;
my $x = $info->{'Camera Model Name'};
return 0 unless $x;
return index(lc($x), $camera) >= 0;
};
}
sub build_filter_latlng {
my ($opts) = @_;
my $distance = $opts->{distance};
my ($lat, $long) = split(',', $opts->{ll}, 2);
my $gis = GIS::Distance->new();
return sub {
my ($exif, undef) = @_;
return 0 unless $exif->HasLocation;
my ($image_lat, $image_long) = $exif->GetLocation;
my $d = $gis->distance($lat, $long, $image_lat, $image_long)->kilometre;
return $d < $distance;
};
}
sub main {
my ($opts, $args) = @_;
my (@paths) = @$args;
pod2usage({ -verbose => 2 }) if $opts->{help};
my $iter = File::Next::files(+{ file_filter => sub { /\.jpg\z/i } }, @paths );
my @filters;
if ($opts->{ll}) {
push(@filters, build_filter_latlng($opts));
}
if ($opts->{camera}) {
push(@filters, build_filter_camera($opts));
}
my $filter = sub {
my @x = @_[0,1];
for my $f (@filters) {
return 0 unless $f->(@x);
}
return 1;
};
while (my $file = $iter->()) {
my $exif = Image::ExifTool->new;
my $info = $exif->ImageInfo($file);
next unless $filter->( $exif, $info );
say "$file";
}
}
my %opts;
GetOptions(
\%opts,
'help|h',
'll=s',
'distance=n',
'camera=s',
) || pod2usage({ -verbose => 1 });
main(\%opts, [@ARGV]);