import-pictures - copy/move pictures from a directory
import-pictures [options]
import-pictures copies or moves pictures from one directory (for example from a mounted camera) to another directory. You can choose date ranges from within to copy the images. For example you can just choose the pictures from one day of the event in one directory and after that you can move the other day into another directory.
Prints out a brief help
Enable additional debug informations
Move pictures instead of copying
Use exif metadata as data instead of creation date of the file
Comma separated list of file extensions to work on (default jpg and nef)
From which directory pictures should be copied.
Where to copy the pictures to. If targetdir does not exist it will be created.
From which date images should get copied. You can use relative dates as used in the date command.
Until which date images should get copied. You can use relative dates as used in the date command.
Starting number for the _COUNTER_ template
Use exifautotran to rotate the pictures automatically
Don't do anything, just print out what would happen.
You can rename files according to a simple template string. Currently the following template strings are supported:
This is a counter which gets incremented for every picture
Will be replaced by the according date strings.
NOTE: Don't add a file extension the templat or you will end with doubled extensions.
For example 'foobar-_YEAR__MONTH__DAY_-_COUNTER_' results in filenames like foobar-20060916-44.nef
Copy the pictures from the last week up to now based on their exif tag and rename them to last_week-YearMonthDay-Counter.suffix
% import-pictures --exif --start-date 'one week ago' --origin /mnt/cam/DCIM/ --to Bilder/Last_Week --template 'last_week-_YEAR__MONTH__DAY_-_COUNTER_'
Alexander Wirt <formorer@formorer.de>
Copyright 2006 Alexander Wirt <formorer@formorer.de>
This program is licensed under the GNU General Public License v2. You may fold, spindle, and mutilate this software under the terms of the GPL. =cut
use strict; use English; use Pod::Usage; use Getopt::Long; use File::Path qw(mkpath); use Data::Dumper; use Image::ExifTool 'ImageInfo'; use Date::Format; use Time::ParseDate; use File::Copy; use File::Basename;
Getopt::Long::Configure ("bundling");
my $filetypes = ''; my ($debug,$help, $exif, $move, $simulate, $rotate) = 0; my ($rename,$to, $start_date) = ''; my $start_date = "1970/1/2"; #if you have soooo old files you have a problem... my $end_date = localtime (time); my $startnum = 1; my (@from, @files);
GetOptions( | 'help|h' => \$help, #Help function | |
'debug|d' => \$debug, #print more details | ||
'move|m' => \$move, #move the pictures instead of copying | ||
'exif|x' => \$exif, #use exifdate for date selection | ||
'filetypes|f=s' => \$filetypes, #which filetypes to select | ||
'to|t=s' => \$to, #where to copy the images | ||
'origin|o=s' => \@from, #from where to opy the images | ||
'start-date|s=s' => \$start_date, #from when to copy images | ||
'end-date|e=s' => \$end_date, #until when to copy images | ||
'template|T=s' => \$rename, | ||
'start-num|n=i' => \$startnum, | ||
'simulate' => \$simulate, | ||
'rotate|r' => \$rotate, | ||
); |
pod2usage(1) if $help;
die "Need target directory" unless $to; die "Need source directory" unless @from;
if (! $filetypes) { $filetypes = 'jpg|nef'; } else { $filetypes = join('|', split(/,/,$filetypes)); }
foreach my $dir (@from) {
warn "$dir";
scan_dir($dir)
;
}
#check the target directory
if (-d "$to" && -w "$to") {
print "Target '$to' already exists\n";
} else {
eval { mkpath($to)
};
if ($@) {
print "Couldn't create target directory '$to': $@";
}
}
my $i = $startnum;
foreach my $file (@files) {
my $picture_date;
#Receive the creation date of the file
if ($exif) {
my $info = ImageInfo("$file")
;
$picture_date = $info->{'CreateDate'} || $info->{'DateTimeOriginal'};
if (! $picture_date ) {
print "Could not read exif data of $file - ignored\n";
next;
}
if ($picture_date =~ /^([\d:]+)\s+(.*)$/) { my $time = $2; my $day = $1; $day =~ s/:/\//g; $picture_date = "$day $time"; } } else { $picture_date = time2str("%a %b %e %T %Y", (stat($file))[10]); }
my $targetfile; if ($rename) { $targetfile = evaluate_template($file, $picture_date, $i); print basename($file) . " evaluates to $targetfile\n" if $debug; $i++; } else { $targetfile = basename($file); }
#check if the file fits into the date if (check_date({ start_date => $start_date, end_date => $end_date, picture_date=> $picture_date})) { #create directories first if ($targetfile =~ /\//) { my $directory = dirname($targetfile); eval { mkpath("$to/$directory") }; if ($@) { print "Couldn't create target directory '$to/$directory': $@"; } } if ($move) { print "Move file from $file to $to/$targetfile\n"; move("$file", "$to/$targetfile") unless $simulate; } else { print "Copy file from $file to $to/$targetfile\n"; copy("$file", "$to/$targetfile") unless $simulate; } if ($rotate) { print "Rotate $to/$targetfile\n"; my @args = ("exifautotran", "$to/$targetfile"); system(@args) unless $simulate; } } else { print "$file does not match criteria\n" if $debug; } }
sub check_date ($) { my $date = shift; my $start_date = parsedate($date->{start_date}); my $end_date = parsedate($date->{end_date}); my $picture_date = parsedate($date->{picture_date}); print "Start: " . time2str("%a %b %e %T %Y\n", $start_date) if $debug; print "End: " . time2str("%a %b %e %T %Y\n", $end_date) if $debug; print "File: " . time2str("%a %b %e %T %Y\n", $picture_date) if $debug; return 1 if ( $picture_date >= $start_date && $picture_date <= $end_date ); return 0; }
sub evaluate_template($) {
my ($filename,$picture_date, $i) = @_;
my($filename, $directories, $suffix) = fileparse($filename, qr/\.[^.]*/);
my $fname = $rename;
$suffix = lc($suffix)
;
my $seconds = parsedate("$picture_date"); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($seconds); $year += 1900; $mon += 1; $mon = sprintf("%02d", $mon); $mday = sprintf("%02d", $mday);
$hour = sprintf("%02d", $hour); $min = sprintf("%02d", $min); $sec = sprintf("%02d", $sec);
print "Template: $fname\n" if $debug; $fname =~ s/_DAY_/$mday/g; $fname =~ s/_MONTH_/$mon/g; $fname =~ s/_YEAR_/$year/g;
$fname =~ s/_HOUR_/$hour/g; $fname =~ s/_MINUTE_/$min/g; $fname =~ s/_SEC_/$sec/g;
$fname =~ s/_COUNTER_/$i/g;
$fname .= "$suffix"; return $fname; }
sub scan_dir ($) {
my $dir = shift;
local *DIR;
print "Reading: $dir\n" if $debug;
opendir (DIR, "$dir") || die "Can't open $dir: $!";
while (my $entry = readdir(DIR)) {
next if $entry =~ /^\.{1,2}$/;
if (-d "$dir/$entry") {
scan_dir("$dir/$entry")
;
}
push @files, "$dir/$entry" if $entry =~ /^[^.].*\.($filetypes)$/i
}
closedir DIR;
}
#!/usr/bin/perl # $Id: import-pictures 14 2007-05-22 20:00:19Z formorer $
# Copyright (C) 2007 Alexander Wirt <formorer@formorer.de> # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #
import-pictures - copy/move pictures from a directory
import-pictures [options]
import-pictures copies or moves pictures from one directory (for example from a mounted camera) to another directory. You can choose date ranges from within to copy the images. For example you can just choose the pictures from one day of the event in one directory and after that you can move the other day into another directory.
Prints out a brief help
Enable additional debug informations
Move pictures instead of copying
Use exif metadata as data instead of creation date of the file
Comma separated list of file extensions to work on (default jpg and nef)
From which directory pictures should be copied.
Where to copy the pictures to. If targetdir does not exist it will be created.
From which date images should get copied. You can use relative dates as used in the date command.
Until which date images should get copied. You can use relative dates as used in the date command.
Starting number for the _COUNTER_ template
Use exifautotran to rotate the pictures automatically
Don't do anything, just print out what would happen.
You can rename files according to a simple template string. Currently the following template strings are supported:
This is a counter which gets incremented for every picture
Will be replaced by the according date strings.
NOTE: Don't add a file extension the templat or you will end with doubled extensions.
For example 'foobar-_YEAR__MONTH__DAY_-_COUNTER_' results in filenames like foobar-20060916-44.nef
Copy the pictures from the last week up to now based on their exif tag and rename them to last_week-YearMonthDay-Counter.suffix
% import-pictures --exif --start-date 'one week ago' --origin /mnt/cam/DCIM/ --to Bilder/Last_Week --template 'last_week-_YEAR__MONTH__DAY_-_COUNTER_'
Alexander Wirt <formorer@formorer.de>
Copyright 2006 Alexander Wirt <formorer@formorer.de>
This program is licensed under the GNU General Public License v2. You may fold, spindle, and mutilate this software under the terms of the GPL. =cut
use strict; use English; use Pod::Usage; use Getopt::Long; use File::Path qw(mkpath); use Data::Dumper; use Image::ExifTool 'ImageInfo'; use Date::Format; use Time::ParseDate; use File::Copy; use File::Basename;
Getopt::Long::Configure ("bundling");
my $filetypes = ''; my ($debug,$help, $exif, $move, $simulate, $rotate) = 0; my ($rename,$to, $start_date) = ''; my $start_date = "1970/1/2"; #if you have soooo old files you have a problem... my $end_date = localtime (time); my $startnum = 1; my (@from, @files);
GetOptions( | 'help|h' => \$help, #Help function | |
'debug|d' => \$debug, #print more details | ||
'move|m' => \$move, #move the pictures instead of copying | ||
'exif|x' => \$exif, #use exifdate for date selection | ||
'filetypes|f=s' => \$filetypes, #which filetypes to select | ||
'to|t=s' => \$to, #where to copy the images | ||
'origin|o=s' => \@from, #from where to opy the images | ||
'start-date|s=s' => \$start_date, #from when to copy images | ||
'end-date|e=s' => \$end_date, #until when to copy images | ||
'template|T=s' => \$rename, | ||
'start-num|n=i' => \$startnum, | ||
'simulate' => \$simulate, | ||
'rotate|r' => \$rotate, | ||
); |
pod2usage(1) if $help;
die "Need target directory" unless $to; die "Need source directory" unless @from;
if (! $filetypes) { $filetypes = 'jpg|nef'; } else { $filetypes = join('|', split(/,/,$filetypes)); }
foreach my $dir (@from) {
warn "$dir";
scan_dir($dir)
;
}
#check the target directory
if (-d "$to" && -w "$to") {
print "Target '$to' already exists\n";
} else {
eval { mkpath($to)
};
if ($@) {
print "Couldn't create target directory '$to': $@";
}
}
my $i = $startnum;
foreach my $file (@files) {
my $picture_date;
#Receive the creation date of the file
if ($exif) {
my $info = ImageInfo("$file")
;
$picture_date = $info->{'CreateDate'} || $info->{'DateTimeOriginal'};
if (! $picture_date ) {
print "Could not read exif data of $file - ignored\n";
next;
}
if ($picture_date =~ /^([\d:]+)\s+(.*)$/) { my $time = $2; my $day = $1; $day =~ s/:/\//g; $picture_date = "$day $time"; } } else { $picture_date = time2str("%a %b %e %T %Y", (stat($file))[10]); }
my $targetfile; if ($rename) { $targetfile = evaluate_template($file, $picture_date, $i); print basename($file) . " evaluates to $targetfile\n" if $debug; $i++; } else { $targetfile = basename($file); }
#check if the file fits into the date if (check_date({ start_date => $start_date, end_date => $end_date, picture_date=> $picture_date})) { #create directories first if ($targetfile =~ /\//) { my $directory = dirname($targetfile); eval { mkpath("$to/$directory") }; if ($@) { print "Couldn't create target directory '$to/$directory': $@"; } } if ($move) { print "Move file from $file to $to/$targetfile\n"; move("$file", "$to/$targetfile") unless $simulate; } else { print "Copy file from $file to $to/$targetfile\n"; copy("$file", "$to/$targetfile") unless $simulate; } if ($rotate) { print "Rotate $to/$targetfile\n"; my @args = ("exifautotran", "$to/$targetfile"); system(@args) unless $simulate; } } else { print "$file does not match criteria\n" if $debug; } }
sub check_date ($) { my $date = shift; my $start_date = parsedate($date->{start_date}); my $end_date = parsedate($date->{end_date}); my $picture_date = parsedate($date->{picture_date}); print "Start: " . time2str("%a %b %e %T %Y\n", $start_date) if $debug; print "End: " . time2str("%a %b %e %T %Y\n", $end_date) if $debug; print "File: " . time2str("%a %b %e %T %Y\n", $picture_date) if $debug; return 1 if ( $picture_date >= $start_date && $picture_date <= $end_date ); return 0; }
sub evaluate_template($) {
my ($filename,$picture_date, $i) = @_;
my($filename, $directories, $suffix) = fileparse($filename, qr/\.[^.]*/);
my $fname = $rename;
$suffix = lc($suffix)
;
my $seconds = parsedate("$picture_date"); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($seconds); $year += 1900; $mon += 1; $mon = sprintf("%02d", $mon); $mday = sprintf("%02d", $mday);
$hour = sprintf("%02d", $hour); $min = sprintf("%02d", $min); $sec = sprintf("%02d", $sec);
print "Template: $fname\n" if $debug; $fname =~ s/_DAY_/$mday/g; $fname =~ s/_MONTH_/$mon/g; $fname =~ s/_YEAR_/$year/g;
$fname =~ s/_HOUR_/$hour/g; $fname =~ s/_MINUTE_/$min/g; $fname =~ s/_SEC_/$sec/g;
$fname =~ s/_COUNTER_/$i/g;
$fname .= "$suffix"; return $fname; }
sub scan_dir ($) {
my $dir = shift;
local *DIR;
print "Reading: $dir\n" if $debug;
opendir (DIR, "$dir") || die "Can't open $dir: $!";
while (my $entry = readdir(DIR)) {
next if $entry =~ /^\.{1,2}$/;
if (-d "$dir/$entry") {
scan_dir("$dir/$entry")
;
}
push @files, "$dir/$entry" if $entry =~ /^[^.].*\.($filetypes)$/i
}
closedir DIR;
}