#!/usr/bin/perl -w # # Konica Minolta Dynax 7D downloader # # Designed by Flex. # Written by Flex from FleXoft. # (flex@fleischmann.hu) # # v1.31, 2005.06.27. Budapest, FleXoft # Add: EXIF field parameters # # v1.30, 2005.05.02. Budapest, FleXoft # Chg: new sorting algorithm at directories # # v1.21, 2005.04.11. Budapest, FleXoft # Chg: the engine can handle all of the filetypes (jpg, jpe, thm, mrw) coming from the camera # Chg: minor code brush # # v1.11, 2005.03.20. Budapest, FleXoft # Bfx: sort directory list # # v1.10, 2005.03.16. Budapest, FleXoft # Add: command line options # Add: EXIF support -e option # # v1.00, 2005.03.14. Budapest, FleXoft # Rls: first release # # Documentation: # -------------- # # DOWNLOAD "jhead.exe" for MS Windows if you need from here: http://www.sentex.net/~mwandel/jhead/ # # TODO: # ----- # # -i interactive mode # -E text editor path # # ========================================================================= # # 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, 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; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # # ************************************************************************* # # XXXXXXX XXX XXX XXX XXX X # XX X XX XX XX XX XX XX # XX X XX XXXXX XXX XXXX XX XXXXX # XXXX XX XX X X XX XX XXXXX XX # XX X XX XXXXXXX XXX XX XX XX XX # XX XX XX XX XX XX XX XX XX XX # XXXX XXXX XXXXX XXX XXX XXXX XXXX XXX # # ************************************************************************* use strict; use Getopt::Std; use File::Basename; use File::Copy; &getopts ("vqpcihs:enE:S:T:C:t:g:l:"); our $opt_v; our $opt_q; our $opt_p; our $opt_c; our $opt_h; our $opt_s; our $opt_e; our $opt_i; our $opt_E; our $opt_S; our $opt_T; our $opt_C; our $opt_n; our $opt_t; our $opt_g; our $opt_l; my $OS_win = ($^O eq "MSWin32") ? 1 : 0; if ($OS_win) { ########################## # MS Windows environment # ########################## # use Win32; } my $byear = substr((localtime(time))[5]+1900, 0, 3); my $serialnumber = 0; my $SOURCE = "/Volumes/KMD7D/DCIM/"; my @sourcefiles; my $TARGET = "/Volumes/BACKUP\ 01/Private/Photos/Minolta\ pictures/2011Q1/"; my $filename = "KM"; my $COUNTERFILE = "/Volumes/BACKUP\ 01/Private/Photos/Minolta\ pictures/etc/km.counter"; my $TEXTEDITOR = "vi"; my $JHEAD = "jhead"; my $TITLE = ""; my $PHOTOGRAPHER = "FLEISCHMANN György, flex"; my $PLACE = "Budapest, HUNGARY"; my $directorycounter = 1; my $summafiles = 0; ################ # Version Info ################ # # based on Jux's code # open my $MYSELF, "<$0" or die; my ($VERSION, $SUBVERSION); while (<$MYSELF>) { if ( /^# v(\d+)\.(\d{2})/ ) { ($VERSION, $SUBVERSION) = ($1, $2); last; } die "No version info found in $0" unless /^#/; } close $MYSELF or die; my $PROGNAME = $0; $PROGNAME =~ s{.*(/|\\)}{}; print "$PROGNAME v$VERSION.$SUBVERSION\n" if ( ! defined ($opt_q) ); if ( defined ($opt_v) ) { exit; } if ( defined ($opt_h) ) { print "\nHelp:\n"; print " -q\tToggle quiet mode.\n"; print " -v\tShow only version information.\n"; print " -p\tPreview only.\n"; print " -s\tSpecify the next serial number.\n"; print " -e\tCreate EXIF data file for my photoalbum_generator.\n"; print " -S\tSpecify the source directory [default: $SOURCE]\n"; print " -T\tSpecify the target directory [default: $TARGET]\n"; print " -C\tSpecify the counter file path [default: $COUNTERFILE]\n"; print " -t\tEXIF title field [default: $TITLE].\n"; print " -g\tEXIF name of the photographer field [default: $PHOTOGRAPHER].\n"; print " -l\tEXIF place field [default: $PLACE].\n"; print " -n\tNo MS Windows popup message.\n"; print " -h\tShow usage. This is.\n\n"; exit; } if ( defined ($opt_S) ) { $SOURCE = $opt_S; } if ( defined ($opt_T) ) { $TARGET = $opt_T; } if ( defined ($opt_C) ) { $COUNTERFILE = $opt_C; } if ( defined ($opt_t) ) { $TITLE = $opt_t; } if ( defined ($opt_g) ) { $PHOTOGRAPHER = $opt_g; } if ( defined ($opt_l) ) { $PLACE = $opt_l; } #################################################### # collect the files from the collected directories #################################################### # read source directory list before open the counter file my @directory = sort( { if ( length($a) == 8 && length($b) == 8 ) { substr($a, 3).substr($a, 0, 3) cmp substr($b, 3).substr($b, 0, 3); } else { return $a cmp $b; } } &open_dir($SOURCE) ); # read the last counter number from file if ( -f $COUNTERFILE && ! defined ($opt_s) ) { open (FH, "$COUNTERFILE"); while () { chomp($serialnumber = $1) if (m/^SERIAL#\s+(.*)$/); }; close (FH); } else { print "No counter file [$COUNTERFILE] found!\n"; } $serialnumber = $opt_s if ( defined ($opt_s) ); print "The next serial number will be: [$serialnumber]\n" if ( ! defined ($opt_q) ); # do it foreach my $directory (@directory) { next if ( $directory eq "." || $directory eq ".." ); # is this a directory if ( -d $SOURCE.$directory) { # directory name filtering NNNYMMDD next if ( $directory !~ m/\d\d\d(\d)(\d\d)(\d\d).*/ ); print "==[$directorycounter/".($#directory-2)."]==Directory found: [$directory]\n" if ( ! defined ($opt_q) ); my ($year, $month, $day) = ($byear.$1, $2, $3); my $filecounter = 0; my $filesperdirectory = 0; # collect the filenames into a hash called %filenames to get the unique name list my %filenames = (); # create unique filename hash foreach my $file (&open_dir($SOURCE.$directory)) { next if ( $file eq "." || $file eq ".." ); next if ( $file !~ m/^PICT\d\d\d\d\d*\.\w\w\w/i ); my $key = fileparse($file, '\.\w\w\w'); $filenames{$key} = ""; $filesperdirectory++; } foreach my $file (sort { uc($a) cmp uc($b); } (keys %filenames)) { # move the file(s) my $jpgextension = ""; # it can be jpe or jpg # JPE if ( -f $SOURCE.$directory."\/".$file.".JPE" ) { $filecounter++; print " Moving [$filecounter/$filesperdirectory] [".$SOURCE.$directory."\/".$file.".JPE] to [".$TARGET.$filename.$year.$month.$day."_".$serialnumber.".jpe]\n" if ( ! defined ($opt_q) ); move($SOURCE.$directory."/".$file.".JPE", "$TARGET"."$filename"."$year"."$month.$day"."_".$serialnumber.".jpe") or die "Error moving: $!" if ( ! defined ($opt_p) ); $jpgextension = ".jpe"; } # JPG if ( -f $SOURCE.$directory."/".$file.".JPG" ) { $filecounter++; print " Moving [$filecounter/$filesperdirectory] [".$SOURCE.$directory."/".$file.".JPG] to [".$TARGET.$filename.$year.$month.$day."_".$serialnumber.".jpg]\n" if ( ! defined ($opt_q) ); move($SOURCE.$directory."/".$file.".JPG", $TARGET.$filename.$year.$month.$day."_".$serialnumber.".jpg") or die "Error moving: $!" if ( ! defined ($opt_p) ); $jpgextension = ".jpg"; } # MRW if ( -f $SOURCE.$directory."/".$file.".MRW" ) { $filecounter++; print " Moving [$filecounter/$filesperdirectory] [".$SOURCE.$directory."/".$file.".MRW] to [".$TARGET.$filename.$year.$month.$day."_".$serialnumber.".mrw]\n" if ( ! defined ($opt_q) ); move($SOURCE.$directory."/".$file.".MRW", $TARGET.$filename.$year.$month.$day."_".$serialnumber.".mrw") or die "Error moving: $!" if ( ! defined ($opt_p) ); } # THM if ( -f $SOURCE.$directory."/".$file.".THM" ) { $filecounter++; print " Moving [$filecounter/$filesperdirectory] [".$SOURCE.$directory."/".$file.".THM] to [".$TARGET.$filename.$year.$month.$day."_".$serialnumber.".thm]\n" if ( ! defined ($opt_q) ); move($SOURCE.$directory."/".$file.".THM", $TARGET.$filename.$year.$month.$day."_".$serialnumber.".thm") or die "Error moving: $!" if ( ! defined ($opt_p) ); } # EXIF info if ( defined ($opt_e) && ! defined ($opt_p) && -f $TARGET.$filename.$year.$month.$day."_".$serialnumber.$jpgextension ) { open (PIPE, "$JHEAD \"".$TARGET.$filename.$year.$month.$day."_".$serialnumber.$jpgextension."\" |") or die "Error running $JHEAD: $!"; my @jhead = ; close PIPE; # save EXIF info open (FH, ">".$TARGET.$filename.$year.$month.$day."_".$serialnumber.".txt") or die "$0: failed to open handle for ".$TARGET.$filename.$year.$month.$day."_".$serialnumber.".txt: $!!\n"; print FH "#\n"; print FH "# EXIF Title : $TITLE\n"; print FH "# EXIF Photographer : $PHOTOGRAPHER\n"; print FH "# EXIF Place : $PLACE\n"; print FH "#\n"; for ( @jhead ) { chomp; next if ( m/^$/ ); print FH "# EXIF $_\n"; } print FH "#\n"; print FH "# Generated by: $PROGNAME v$VERSION.$SUBVERSION\n"; print FH "# You can add some extra HTML text here for photoalbum_generator:\n"; close (FH); } $serialnumber++; } $summafiles += $filecounter; if ( $filecounter == 0 ) { print ("and it is empty!\n") if ( ! defined ($opt_q) ); } else { print (" Found and moved $filecounter file(s).\n") if ( ! defined ($opt_q) ); } $directorycounter++; print " Delete the empty directory.\n" if ( ! defined ($opt_q) ); rmdir ($SOURCE.$directory) if ( ! defined ($opt_p) ); } } if ( $summafiles == 0 ) { print ("No files found!\n") if ( ! defined ($opt_q) ); } else { print "Found $summafiles file(s).\n" if ( ! defined ($opt_q) ); # save the counter number to file if ( ! defined ($opt_p) ) { print "Saving counter number to [$COUNTERFILE]\n" if ( ! defined ($opt_q) ); open (FH, ">$COUNTERFILE") or die "$0: failed to open handle for $COUNTERFILE: $!!\n"; print FH "SERIAL#\t $serialnumber"; close (FH); } &WinMsgBox("$PROGNAME v$VERSION.$SUBVERSION - Reminder", "Check the output screen before you close this window!!!", 48) if ( $OS_win && ! defined ($opt_n) ); } exit 0; ######################################################################################################################## # SUBs ######################################################################################################################## ############################ # open directory structure ############################ sub open_dir ($) { opendir(DIR, $_[0]) or die "$0: failed to open handle for $_[0]: $!!\n"; my @return = readdir(DIR); closedir(DIR); return @return; } ###################### # MS Windows message ###################### sub WinMsgBox { # my ($caption, $message, $icon_buttons) = @_; # my @return = qw/- Ok Cancel Abort Retry Ignore Yes No/; # my $result = Win32::MsgBox($message, $icon_buttons, $caption); # return $return[$result]; } __END__ =head1 NAME B - description =head1 SYNOPSIS Coming soon...