photo-stats

statistics processor for the terminal
git clone https://git.clttr.info/photo-stats.git
Log (Feed) | Files | Refs (Tags) | README | LICENSE

commit 11fbae0e8848fb6f6b9e7b1dae4d1e07f87901a8
parent 04a37e3c4e0752bccc903f1b598270439e33a53b
Author: René Wagner <rwagner@rw-net.de>
Date:   Tue, 25 Aug 2020 21:25:03 +0200

add filtering by value

Diffstat:
MREADME.md | 14+++++++++++---
Mphosta.pl | 57+++++++++++++++++++++++++++++++++++++++------------------
2 files changed, 50 insertions(+), 21 deletions(-)

diff --git a/README.md b/README.md @@ -52,6 +52,7 @@ Additionally the following perl modules need to be installed: - hour - filtering of data by - time range of photos shot + - values in fields in "CONTAINS" and "NOT CONTAINS" mode - custom sorting of output by arbitrary fields - output results in a table view to your terminal @@ -102,13 +103,17 @@ data gathering: This option is saved to the user conf stats querying: - -g : group by time range, defaults to total (which means no grouping by time range) + -g <period> : group by a time period, defaults to total (which means no grouping by period) allowed values: year, month, week, hour -s <fields> : specify the information you want to select, defaults to none (just show number of images) allowed values: maker, model, lensmake, lens, aperture, exposuretime, iso, focallength, focallength35mm multiple fields should be listed comma-separated -t <range> : only take images into account which have been taken in the given timerange <range> must be specified as 'YYYYMMDD-YYYYMMDD', you can omit one value + -f <expr> : filter images based on the given expression, multiple expression can be given comma-separated + this works as a case-insensitive CONTAINS search, multiple expressions need to match all (AND logic) + use "field=value" for CONTAINS and "field!=value" for NOT CONTAINS, value must not include whitespaces + allowed fields: file, maker, model, lensmake, lens, aperture, exposuretime, iso, focallength, focallength35mm -n <number> : limit the resultset to <number> of lines -o <fields> : sort your output by the given fields (sequence matters!) in descending order allowed values: any comma separated combination of the values of -t and -s param and 'count' @@ -119,10 +124,13 @@ examples: load EXIF data of files with the extensions jpg, jpeg and tiff in folder ~/Pictures to the database located in ~/Documents/stats.db phosta -s model -g month -t 20190101-20121231 -o month,count - show number of pictures taken with a specific camera body in 2019 grouped by month, sorted by newest month first + show number of pictures taken in with a specific camera body in 2019 grouped by month, sorted by newest month first phosta -n 10 -s lens -o count - show top 10 lenses used the most over all pictures taken + show top 10 lenses used the most + + phosta -s model -f maker!=ricoh + show camera models where the maker field does not contain the term "ricoh" ``` ## FAQ diff --git a/phosta.pl b/phosta.pl @@ -17,7 +17,7 @@ use File::HomeDir; $Getopt::Std::STANDARD_HELP_VERSION = 'true'; -my $VERSION = '0.8'; +my $VERSION = '0.9'; my $PROGRAM = 'Photo Stats'; my $configfile = catfile(File::HomeDir->my_home, '.phosta.conf'); @@ -34,10 +34,11 @@ our $opt_v=0; our $opt_n=undef; our $opt_o='count'; our $opt_r=0; +our $opt_f=undef; getconfig($configfile); -getopts('vcrp:n:g:s:t:D:E:o:') or die "Invalid parameters provided! See 'phosta --help' for more details."; +getopts('vcrp:n:g:s:t:D:E:o:f:') or die "Invalid parameters provided! See 'phosta --help' for more details."; validate() or die "Invalid parameters provided! See 'phosta --help' for more details."; my $dsn = "DBI:SQLite:dbname=$opt_D"; @@ -83,6 +84,7 @@ sub validate $opt_E =~ /^([a-z]{2,4}){1,}(\,[a-z]{2,4}){0,}$/ or return 0; + !defined($opt_f) || $opt_f =~ /^[\w]{2,}(!){0,1}=[\w]{1,}(,[\w]{2,}(!){0,1}=[\w]{1,}){0,}$/ or return 0; return 1; } @@ -139,7 +141,7 @@ sub populate $apert = ($apert ne '-') ? sprintf("%.1f", $apert) : $apert; $fl = ($fl ne '-') ? sprintf("%.1f", $fl) : $fl; $fl35 = ($fl35 ne '-') ? POSIX::lround($fl35) : $fl35; - $exposuretime = (looks_like_number($exposuretime) && $exposuretime < 1) ? "1/". POSIX::lround(1/$exposuretime) : $exposuretime; + $exposuretime = (looks_like_number($exposuretime) && $exposuretime < 1 && $exposuretime != 0) ? "1/". POSIX::lround(1/$exposuretime) : $exposuretime; if ($datetimeoriginal eq '0000:00:00 00:00:00') { $datetimeoriginal = '-'; } my $stmt = "INSERT OR REPLACE INTO photos (file, maker, model, lensmake, lens, focallength, focallength35mm, aperture, exposuretime, iso, flash, datetimeoriginal) @@ -154,40 +156,40 @@ sub populate sub get_sql { - my ($selected, $grouping, $order, $timerange) = @_; + my ($selected, $grouping, $order, $timerange, $filter) = @_; my $fieldlist = ''; - my $grouplist = ''; + my @grouparray; my $orderlist = ''; - my $wherelist = ''; + my @wherearray; given ($grouping) { when ('month') { $fieldlist = "IFNULL(strftime('%Y/%m', datetimeoriginal), '-') as month,"; - $grouplist = "strftime('%Y/%m', datetimeoriginal)"; + push @grouparray, "strftime('%Y/%m', datetimeoriginal)"; } when ('week') { $fieldlist = "IFNULL(strftime('%Y/%W', datetimeoriginal), '-') as week,"; - $grouplist = "strftime('%Y/%W', datetimeoriginal)"; + push @grouparray, "strftime('%Y/%W', datetimeoriginal)"; } when ('year') { $fieldlist = "IFNULL(strftime('%Y', datetimeoriginal), '-') as year,"; - $grouplist = "strftime('%Y', datetimeoriginal)"; + push @grouparray, "strftime('%Y', datetimeoriginal)"; } when ('hour') { $fieldlist = "IFNULL(strftime('%H', datetimeoriginal), '-') as hour,"; - $grouplist = "strftime('%H', datetimeoriginal)"; + push @grouparray, "strftime('%H', datetimeoriginal)"; } } if (defined($selected)) { $fieldlist = $fieldlist . $selected . ', '; - $grouplist .= ($grouplist ne '' ? ',' : '') . $selected; + push @grouparray, $selected; } if (defined($order)) @@ -202,16 +204,28 @@ sub get_sql my ($from, $to) = split(/\-/, $timerange); if ($from ne '') { - $wherelist = 'datetimeoriginal >= \''. substr($from, 0, 4) .'-'. substr($from, 4, 2) .'-'. substr($from, 6, 2) .'\''; + push @wherearray, 'datetimeoriginal >= \''. substr($from, 0, 4) .'-'. substr($from, 4, 2) .'-'. substr($from, 6, 2) .'\''; } if ($to ne '') { - $wherelist .= ($wherelist ne '' ? ' AND ' : '') . 'datetimeoriginal <= \''. substr($to, 0, 4) .'-'. substr($to, 4, 2) .'-'. substr($to, 6, 2) .'\''; + push @wherearray, 'datetimeoriginal <= \''. substr($to, 0, 4) .'-'. substr($to, 4, 2) .'-'. substr($to, 6, 2) .'\''; } } - if ($grouplist ne '') { $grouplist = 'GROUP BY '. $grouplist; } - if ($wherelist ne '') { $wherelist = 'WHERE ' . $wherelist; } + if (defined($filter)) + { + my (@filters) = split /\,/, $filter; + foreach (@filters) + { + my ( $sub1, $sub2, $sub3 ) = split /(!){0,1}=/, $_; + push @wherearray, $sub1 . ($_ =~ /!/ ? ' NOT ' : '') . " LIKE '%$sub3%'"; + } + } + + my $wherelist = ''; + my $grouplist = ''; + if (scalar @grouparray) { $grouplist = 'GROUP BY '. join(', ', @grouparray); } + if (scalar @wherearray) { $wherelist = 'WHERE ' . join(' AND ', @wherearray); } return "SELECT $fieldlist count(file) as count FROM photos $wherelist $grouplist $orderlist"; } @@ -225,9 +239,9 @@ sub query say "Querying database $opt_D with $total_count entries..."; say ''; $total_count > 0 or return; - - if ($opt_v) { say '### SQL Statement: '. get_sql($opt_s, $opt_g, $opt_o, $opt_t); } - my $stmt = $dbh->prepare(get_sql($opt_s, $opt_g, $opt_o, $opt_t)); + my $sql = get_sql($opt_s, $opt_g, $opt_o, $opt_t, $opt_f); + if ($opt_v) { say '### SQL Statement: '. $sql; } + my $stmt = $dbh->prepare($sql); $stmt->execute(); my $rows = $stmt->fetchall_arrayref; @@ -317,6 +331,10 @@ sub main::HELP_MESSAGE say ' multiple fields should be listed comma-separated'; say ' -t <range> : only take images into account which have been taken in the given timerange'; say ' <range> must be specified as \'YYYYMMDD-YYYYMMDD\', you can omit one value'; + say ' -f <expr> : filter images based on the given expression, multiple expression can be given comma-separated'; + say ' this works as a case-insensitive CONTAINS search, multiple expressions need to match all (AND logic)'; + say ' use "field=value" for CONTAINS and "field!=value" for NOT CONTAINS, value must not include whitespaces'; + say ' allowed fields: file, maker, model, lensmake, lens, aperture, exposuretime, iso, focallength, focallength35mm'; say ' -n <number> : limit the resultset to <number> of lines'; say ' -o <fields> : sort your output by the given fields (sequence matters!) in descending order'; say ' allowed values: any comma separated combination of the values of -t and -s param and \'count\''; @@ -331,4 +349,7 @@ sub main::HELP_MESSAGE say ''; say ' phosta -n 10 -s lens -o count'; say ' show top 10 lenses used the most'; + say ''; + say ' phosta -s model -f maker!=ricoh'; + say ' show camera models where the maker field does not contain the term "ricoh"'; }