summaryrefslogtreecommitdiffabout
authorAndy Shevchenko <andy@smile.org.ua>2006-10-06 11:54:08 (GMT)
committer Andy Shevchenko <andy@smile.org.ua>2006-10-06 11:54:08 (GMT)
commit03cc05032e79823648523bdd434d4f1b3d86a41b (patch) (side-by-side diff)
tree29a13765f37f045b12b945d0a40877e76ae3aaa8
parent32b6758f8688e0aea2210eb335bd9be6c8c79ff8 (diff)
downloadrenrot-03cc05032e79823648523bdd434d4f1b3d86a41b.tar.gz
renrot-03cc05032e79823648523bdd434d4f1b3d86a41b.tar.bz2
Move main() to the end of file. Refactoring: configOptions -> cfgOpts.
Remove --color. Add 'use color' to configuration file ("use color = Yes" is default). Processing message look tunned, now it shows '(m of n)' file processed. Fix tag target in the Makefile. Possible fix bug with clearing EXIFs when --no-backup is given git-svn-id: file:///svnroot/renrot/branches/RENROT_STABLE@268 fe2816f4-e837-0410-b10a-f608c9d244a1
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--ChangeLog8
-rw-r--r--Makefile.PL2
-rw-r--r--README39
-rw-r--r--TODO10
-rw-r--r--etc/colors.conf3
-rw-r--r--etc/renrot.conf2
-rwxr-xr-xrenrot435
7 files changed, 263 insertions, 236 deletions
diff --git a/ChangeLog b/ChangeLog
index 1c46ef5..f8cb281 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,11 @@
$Log$
+Revision 1.148.2.7 2006/10/06 11:54:08 andy
+Move main() to the end of file. Refactoring: configOptions -> cfgOpts.
+Remove --color. Add 'use color' to configuration file ("use color = Yes" is default).
+Processing message look tunned, now it shows '(m of n)' file processed.
+Fix tag target in the Makefile.
+Possible fix bug with clearing EXIFs when --no-backup is given
+
Revision 1.148.2.6 2006/09/02 19:03:17 andy
Release as 0.24.
@@ -617,4 +624,3 @@ Id keyword is added to renrot file.
Revision 1.1 2005/10/17 13:39:38 zeus
ChangeLog file is added. Its the very begining.
-
diff --git a/Makefile.PL b/Makefile.PL
index 4579c16..9e3262e 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -22,7 +22,7 @@ rpm : tardist
# CVS tagging
tag :
- cvs tag "renrot_$(shell date +'%Y%m%d%H%M%S')"
+ $(PERLRUN) -e 'use POSIX qw(strftime); $$date = strftime("%Y%m%d%H%M%S", localtime()); system("cvs tag $(NAME)_$$date");'
END
return $postamble;
}
diff --git a/README b/README
index a8d985f..05daca3 100644
--- a/README
+++ b/README
@@ -96,25 +96,40 @@ the script:
renrot --no-mtime *.jpg
-RESTRICTIONS
-------------
+RESTRICTIONS AND BUGS
+------------ --- ----
+
+RenRot has some restrictions and known bugs at runtime.
+
+1. Script handles a whole directory without recursion and only with one
+extension of files.
+
+2. Algorithm treat each file with given extension as the image. Otherwise,
+file will be renamed to the current time stamp when --no-rename option is
+omitted.
-RenRot has some restrictions at runtime. First off, script handles a whole
-directory without recursion and only with one extension of files. Second,
-algorithm treat each file with given extension as the image. Otherwise, file
-will be renamed to the current time stamp when --no-rename option is omitted.
-Third, rename operation is not permited between different partitions due to
-hard link technology used (this will be avoided in future). Rotation process
-is available only on JPEG files.
+3. Rename operation is not permited between different partitions due to hard
+link technology used (this will be avoided in future).
-It seems that for Perl v.5.8.7 and 5.8.8, at least on FreeBSD 6 the bug, which
-cause crash of the renrot, exists. In case when total amount of the files size
-to process is bigger than RAM amount, the renrot falls with error:
+4. Rotation process is available only on JPEG files.
+
+5. It seems that for Perl v.5.8.7 and 5.8.8, at least on FreeBSD 6 the bug,
+which cause crash of the renrot, exists. In case when total amount of the
+files size to process is bigger than RAM amount, the renrot falls with error:
Out of memory during "large" request for XXXX bytes ...
This doesn't occure for Perl v.5.6.1.
+6. Still no way to set the tags with the same name but located in the
+different groups.
+
+7. The colorization is started after the configuration files were parsed.
+While that is not happened the messages will be colorized by default color
+scheme.
+
+8. The colorization is not working under Windows platform.
+
DEBUGGING
---------
diff --git a/TODO b/TODO
index 29b68b0..c96e996 100644
--- a/TODO
+++ b/TODO
@@ -7,6 +7,13 @@ TODO SEMANTICS
q optional feature
+BUGS
+
+- fix cleaning EXIFs when --no-backup is given
+
+- make possible to use same EXIF tags in different groups
+
+
EXIF tags
q to write to some tag the options passed to renrot
@@ -45,6 +52,9 @@ User interface
- GUI on PerlTk (due to WinCE hasn't real console) with some additional
functions such as keywordizer
+- to implement help output by topics (sole -h outputs list of topics like
+ rename,rotate,keyword e.t.c. and -h keyword outputs help for keyword related
+
File naming
diff --git a/etc/colors.conf b/etc/colors.conf
index 73297ce..2ac6e60 100644
--- a/etc/colors.conf
+++ b/etc/colors.conf
@@ -3,6 +3,9 @@
#
# Note: These variables can be overriden by command line options.
+# Use colorized output. This NOT works under Win32.
+#Use color = No
+
# Setup colors for different facilities
#Color = debug: 'green'
diff --git a/etc/renrot.conf b/etc/renrot.conf
index 3b564e7..9c478c0 100644
--- a/etc/renrot.conf
+++ b/etc/renrot.conf
@@ -75,3 +75,5 @@
# Use IPC for execution external command
#use IPC = No
+# Use colorized output (not works under MS Windows)
+#use color = Yes
diff --git a/renrot b/renrot
index 67f12f8..dab4ccc 100755
--- a/renrot
+++ b/renrot
@@ -57,7 +57,7 @@ if (defined %Image::ExifTool::UserDefined::RenRot) {
#
# Parsed configuration file in hash
#
-my %configOptions = (
+my %cfgOpts = (
'aggregation delta' => 900,
'aggregation directory' => 'Images',
'aggregation mode' => 'none',
@@ -70,8 +70,9 @@ my %configOptions = (
'mtime' => 1,
'name template' => '%Y%m%d%H%M%S',
'trim' => 1,
+ 'use color' => 1,
'use ipc' => 0,
- );
+ );
########################################################################################
#
@@ -84,7 +85,6 @@ my $aggrTemplate; # template for the files aggregation taken from CLI
my $aggrVirtual; # flag to do links instead real file moving while aggregation
my $aggrVirtDir; # directory name for virtual aggregation
my $backup = 1; # make or not a backup of the original files
-my %colorsFromCli; # colors are got from CLI
my $comfile; # file with commentary
my $configFile; # configuration file
my $countFF = 1; # use fixed field for counter
@@ -186,6 +186,9 @@ my @multOpts = (
'tagfile',
);
+my @files; # array of the sorted filenames to process
+my %filenameshash; # hash for old file names
+
########################################################################################
#
# Colors hash
@@ -203,7 +206,7 @@ my %colors = (
sub printColored {
my $facility = shift;
- if (defined $useColor and $useColor != 0) {
+ if ($cfgOpts{'use color'} != 0) {
if (defined $facility and defined $colors{$facility}) {
print STDERR colored [$colors{$facility}{value}], @_;
return;
@@ -217,7 +220,7 @@ sub printColored {
sub procmsg {
return if ($quiet != 0);
- if (defined $useColor and $useColor != 0) {
+ if ($cfgOpts{'use color'} != 0) {
if (defined $colors{'process'}) {
print colored [$colors{'process'}{value}], @_;
return;
@@ -289,7 +292,6 @@ sub boolConverter {
sub getOptions {
my $showVersion = 0; # need version
my $showHelp = 0; # need help
- my @tmpColors;
my @tmpTags;
my $getOptions = GetOptions (
"aggr-delta=i" => \$aggrDelta,
@@ -299,7 +301,6 @@ sub getOptions {
"aggr-virtual!" => \$aggrVirtual,
"aggr-virtual-directory=s" => \$aggrVirtDir,
"backup!" => \$backup,
- "color=s" => \@tmpColors,
"comment-file=s" => \$comfile,
"config-file|c=s" => \$configFile,
"counter-fixed-field!" => \$countFF,
@@ -340,7 +341,6 @@ sub getOptions {
dbgmsg (3, " --aggr-virtual: ", boolConv($aggrVirtual), "\n") if (defined $aggrVirtual);
dbgmsg (3, " --aggr-virtual-directory: $aggrVirtDir\n") if (defined $aggrVirtDir);
dbgmsg (3, " --backup: ", boolConv($backup), "\n");
- dbgmsg (3, " --color:\n", join("\n", @tmpColors), "\n") if (scalar(@tmpColors) > 0);
dbgmsg (3, " --comment-file: $comfile\n") if (defined $comfile);
dbgmsg (3, " --config-file: $configFile\n") if (defined $configFile);
dbgmsg (3, " --counter-start: $countStart",
@@ -395,20 +395,10 @@ sub getOptions {
$extToProcess =~ s/^\*?\.?/\./ if ($fileCount == 0);
dbgmsg (1, "getOptions(): Process with '$extToProcess' extension.\n");
- # Convert multiple color parameters to colors hash
- foreach my $colorStr (@tmpColors) {
- my %color = strToHash($colorStr, 'reset');
- foreach my $key (keys %color) {
- $colorsFromCli{$key} = $color{$key};
- }
- }
-
# Convert multiple tag parameters to tags hash
foreach my $tagStr (@tmpTags) {
my %tag = strToHash($tagStr);
- foreach my $key (keys %tag) {
- $tagsFromCli{$key} = $tag{$key};
- }
+ map { $tagsFromCli{$_} = $tag{$_} } keys %tag;
}
}
@@ -519,9 +509,7 @@ sub parseConfigFile {
my %hConfig = @_;
if (-f $file) {
my %tmpConfig = getConfig($fc + 1, $file);
- foreach my $key (keys %tmpConfig) {
- $hConfig{$key} = $tmpConfig{$key};
- }
+ map { $hConfig{$_} = $tmpConfig{$_} } keys %tmpConfig;
}
return %hConfig;
}
@@ -556,9 +544,7 @@ sub parseConfig {
@rcFiles = ($file) if (defined $file);
- foreach my $rcfile (@rcFiles) {
- %configOptions = parseConfigFile(0, $rcfile, %configOptions);
- }
+ map { %cfgOpts = parseConfigFile(0, $_, %cfgOpts) } @rcFiles;
}
########################################################################################
@@ -593,158 +579,16 @@ sub dirValidator {
# switchColor() switches to user defined color scheme
#
sub switchColor {
- dbgmsg (1, "Switch to user defined color scheme.\n");
-
# Parse configuration file color set
- foreach my $cKey (keys %configOptions) {
+ foreach my $cKey (keys %cfgOpts) {
next if ($cKey !~ m/^color#\d+#\d+$/); # skip not a color
- my %color = strToHash($configOptions{$cKey}, 'reset');
- foreach my $key (keys %color) {
- $colors{$key} = $color{$key};
- }
- }
-
- # Merge colors from configuration file with command line arguments
- map { $colors{$_} = $colorsFromCli{$_} } keys %colorsFromCli;
-}
-
-########################################################################################
-#
-# MAIN() renames and rotates given files
-#
-
-# parse command line options
-getOptions();
-
-parseConfig($configFile);
-
-switchColor();
-
-# redefining options set in configuration file with set via CLI ones
-$configOptions{'aggregation delta'} = $aggrDelta if (defined $aggrDelta);
-$configOptions{'aggregation directory'} = $aggrDir if (defined $aggrDir);
-$configOptions{'aggregation mode'} = $aggrMode if (defined $aggrMode);
-$configOptions{'aggregation template'} = $aggrTemplate if (defined $aggrTemplate);
-$configOptions{'aggregation virtual'} = $aggrVirtual if (defined $aggrVirtual);
-$configOptions{'aggregation virtual directory'} = $aggrVirtDir if (defined $aggrVirtDir);
-$configOptions{'keywordize'} = $keywordize if (defined $keywordize);
-$configOptions{'keywords file'} = $keywordsFile if (defined $keywordsFile);
-$configOptions{'keywords replace'} = $keywordsReplace if (defined $keywordsReplace);
-$configOptions{'mtime'} = $mtime if (defined $mtime);
-$configOptions{'name template'} = $nameTemplate if (defined $nameTemplate);
-$configOptions{'trim'} = $trim if (defined $trim);
-$configOptions{'use ipc'} = $useIPC if (defined $useIPC);
-
-dbgmsg (1, "main(): Show what would have been happened (no real actions).\n") if ($dryRun != 0);
-
-# Validate aggregation mode possible values
-if (not grep (/^$configOptions{'aggregation mode'}$/, ('none', 'delta', 'template'))) {
- warnmsg ("Aggregation mode isn't correct!\n");
-}
-
-$configOptions{'aggregation directory'} = dirConv($configOptions{'aggregation directory'});
-$configOptions{'aggregation virtual directory'} = dirConv($configOptions{'aggregation virtual directory'});
-
-fatalmsg ("Current or multilevel directory isn't possible now, sorry. Check aggregation arguments.\n"), die
- if ($configOptions{'aggregation mode'} ne "none" and
- (dirValidator($configOptions{'aggregation directory'}) == 0 or
- dirValidator($configOptions{'aggregation virtual directory'}) == 0));
-
-# Calculate ExifTool's verbosity
-my $exiftoolVerbose = ($verbose > $maxVerbosity) ? ($verbose - $maxVerbosity) : 0;
-
-# ExifTool object configuration
-my $exifTool = new Image::ExifTool;
-$exifTool->Options(Binary => 1, Unknown => 1, DateFormat => '%Y%m%d%H%M%S', Verbose => $exiftoolVerbose);
-
-my $file; # file in the directory
-my @files; # array of the sorted filenames to process
-my @filenames; # array of the filenames to process
-my $angleSuffix; # suffix to add to the end of the rotated files
-my $counterSize;
-my %filenameshash; # hash for old file names
-
-chdir ($workDir) || ( fatalmsg ("Can't enter to $workDir!\n"), die );
-
-# All things in ARGV will be treated as file names to process
-@files = @ARGV;
-
-# if no file is given
-if (scalar(@files) == 0) {
- opendir(DIR, "./") || ( fatalmsg ("Can't open $workDir!\n"), die );
- while ( defined ( $file = readdir DIR )) {
- next if (! -f $file); # skip absent file or not a file
- push (@files, $file) if (substr($file, length($file) - length($extToProcess)) eq $extToProcess);
+ my %color = strToHash($cfgOpts{$cKey}, 'reset');
+ map { $colors{$_} = $color{$_} } keys %color;
}
- closedir(DIR);
-}
-
-# independently of @files initialization doing this
-foreach $file ( @files ) {
- next if (! -f $file); # skip absent file or not a file
- next if (grep {/^$file$/} @excludeList); # skip excluded file
- push (@filenames, $file);
-}
-
-# No file to process?
-if (scalar(@filenames) == 0) {
- fatalmsg ("No files to process!\n");
- exit 1;
-}
-
-# Parse configuration file tag set
-foreach my $cKey (keys %configOptions) {
- next if ($cKey !~ m/^tag(file)?#\d+#\d+$/); # skip not a tag or tagfile
- my %tag = strToHash($configOptions{$cKey});
- foreach my $key (keys %tag) {
- $tags{$key} = $tag{$key};
- if ($cKey =~ m/^tagfile/) {
- dbgmsg (4, "main(): Read data from '$tags{$key}{value}' for '$key'\n");
- $tags{$key}{value} = getFileData($tags{$key}{value});
- }
- }
-}
-
-# Put command line arguments to appropriate tags
-$tags{'Comment'} = {value => getFileData($comfile)} if (defined $comfile);
-$tags{'UserComment'} = {value => $userComment} if (defined $userComment);
-# Merge tags from configuration file with command line arguments
-foreach my $key (keys %tagsFromCli) {
- $tags{$key} = $tagsFromCli{$key};
-}
-
-# Print parsed tags at debug level
-my @dbgTags;
-foreach my $key (sort (keys %tags)) {
- my $group = defined $tags{$key}{group} ? $tags{$key}{group} : "";
- my $value = defined $tags{$key}{value} ? $tags{$key}{value} : "";
- push (@dbgTags, "$key [$group] = $value");
-}
-dbgmsg (4, "Tags:\n", join("\n", @dbgTags), "\n") if (scalar(@dbgTags) > 0);
-
-# Preparing the variable, which contains the format of the counter output
-if ($countFF != 0) {
- my $size = length((scalar(@filenames) - 1) * $countStep + $countStart);
- $counterSize = "%." . $size . "d";
- dbgmsg (1, "main(): Counter size: $size (amount files in cache: ", scalar(@filenames), ")\n");
-} else {
- $counterSize = "%d";
-}
-
-# Validate angle value
-if ((defined $rotateAngle and not grep(/^$rotateAngle$/, keys %rotangles)) or
- (defined $rotateThumbnail and not grep(/^$rotateThumbnail$/, keys %rotangles))) {
- fatalmsg ("Angle should be 90, 180 or 270!\n");
- exit 1;
+ dbgmsg (1, "Switch to user defined color scheme.\n");
}
-@files = sort @filenames;
-dbgmsg (4, "main(): Pushed files(", scalar(@files), "):\n", join("\n", @files), "\n");
-
-renRotProcess();
-aggregationProcess();
-
########################################################################################
#
# keywordizer() validates keywords
@@ -771,55 +615,60 @@ sub keywordizer {
# renRotProcess() renames and rotates given file set
#
sub renRotProcess {
+ my $exifToolObj = shift;
+ my $counterSize = shift;
my $fileCounter = $countStart; # file counter
my $newFileName; # the name file to be renamed to
my $info; # ImageInfo object
my @keywordArr; # array for keywords
- if ($configOptions{'keywordize'} != 0) {
- @keywordArr = keywordizer ($configOptions{'keywords file'});
- errmsg ("Keywords file doesn't exist!\n") if (not -e $configOptions{'keywords file'});
+ if ($cfgOpts{'keywordize'} != 0) {
+ @keywordArr = keywordizer ($cfgOpts{'keywords file'});
+ errmsg ("Keywords file doesn't exist!\n") if (not -e $cfgOpts{'keywords file'});
}
if (scalar(@keywordArr) > 0) {
dbgmsg (2, "Keywords count: ", scalar(@keywordArr), "\n");
- if ($configOptions{'keywords replace'} != 0) {
- $exifTool->SetNewValue(Keywords => \@keywordArr);
+ if ($cfgOpts{'keywords replace'} != 0) {
+ $exifToolObj->SetNewValue(Keywords => \@keywordArr);
} else {
- $exifTool->SetNewValue(Keywords => \@keywordArr, AddValue => 1);
+ $exifToolObj->SetNewValue(Keywords => \@keywordArr, AddValue => 1);
}
}
# Convert trim boolean value to string
- my $trimStr = (not defined $configOptions{'trim'} or $configOptions{'trim'}) ? '-trim' : '';
+ my $trimStr = (not defined $cfgOpts{'trim'} or $cfgOpts{'trim'}) ? '-trim' : '';
dbgmsg (1, "renRotProcess(): Trim string: '$trimStr'\n");
dbgmsg (1, "renRotProcess(): Initializing tags ...\n");
foreach my $key (sort (keys %tags)) {
- $exifTool->SetNewValue($key, $tags{$key}{value}, Group => $tags{$key}{group});
+ $exifToolObj->SetNewValue($key, $tags{$key}{value}, Group => $tags{$key}{group});
}
procmsg ("RENAMING / ROTATING\n");
procmsg ("===================\n");
+ my $file_num = scalar(@files);
+ my $file_rem = 0;
foreach my $file (@files) {
- procmsg ("Processing file: $file ...\n");
+ $file_rem++;
+ procmsg ("Processing file: ($file_rem of $file_num) $file ...\n");
# Setup defaults
- $info = $exifTool->ImageInfo($file);
+ $info = $exifToolObj->ImageInfo($file);
# analyzing whether to rotate
- $angleSuffix = rotateFile($exifTool, $info, $file, $trimStr);
+ my $angleSuffix = rotateFile($exifToolObj, $info, $file, $trimStr);
# analyzing whether and how to rename file
- $newFileName = renameFile($exifTool, $info, $file, $fileCounter);
+ $newFileName = renameFile($exifToolObj, $info, $file, $fileCounter, $counterSize, $angleSuffix);
# Writing tags.
- tagWriter($exifTool, $newFileName) if ($noTags == 0);
+ tagWriter($exifToolObj, $newFileName) if ($noTags == 0);
# seting mtime for the file if been asked for
- mtimeSet($exifTool, $info, $newFileName);
+ mtimeSet($exifToolObj, $info, $newFileName);
procmsg ("\n");
@@ -885,6 +734,8 @@ sub renameFile {
my $infoObj = shift;
my $file = shift;
my $fileCounter = shift;
+ my $counterSize = shift;
+ my $angleSuffix = shift;
my $newFileName;
my $unixTime = getUnixTime(getTimestamp($exifToolObj, $infoObj));
@@ -897,9 +748,11 @@ sub renameFile {
my $fileNameOriginal = $exifToolObj->GetValue("RenRotFileNameOriginal");
if (not defined $fileNameOriginal) {
$tags{'RenRotFileNameOriginal'} = {value => $file, group => 'RenRot'};
- $exifTool->SetNewValue("RenRotFileNameOriginal",
- $tags{'RenRotFileNameOriginal'}{value},
- Group => $tags{'RenRotFileNameOriginal'}{group});
+ $exifToolObj->SetNewValue(
+ "RenRotFileNameOriginal",
+ $tags{'RenRotFileNameOriginal'}{value},
+ Group => $tags{'RenRotFileNameOriginal'}{group}
+ );
dbgmsg (2, "renameFile(): set RenRotFileNameOriginal to $file.\n");
} else {
dbgmsg (2, "renameFile(): RenRotFileNameOriginal: $fileNameOriginal.\n");
@@ -910,9 +763,11 @@ sub renameFile {
$newFileName = template2name($exifToolObj,
$infoObj,
- $configOptions{'name template'},
+ $cfgOpts{'name template'},
$fileCounter,
- $file);
+ $file,
+ $counterSize,
+ $angleSuffix);
if ($filenameshash{$newFileName . $ext}) {
$newFileName .= "." . sprintf($counterSize, $fileCounter) . $ext;
} else {
@@ -977,7 +832,7 @@ sub mtimeSet {
my $exifToolObj = shift;
my $infoObj = shift;
my $file = shift;
- if ($configOptions{'mtime'} != 0) {
+ if ($cfgOpts{'mtime'} != 0) {
my $mTime = getUnixTime(getTimestamp($exifToolObj, $infoObj));
if ($dryRun == 0) { utime $mTime, $mTime, $file; }
else { procmsg ("Setting mtime.\n"); }
@@ -1026,33 +881,40 @@ sub exifWriter {
# aggregationProcess() aggregates files to separate directories by request
#
sub aggregationProcess {
- return if ($configOptions{'aggregation mode'} eq "none");
+ return if ($cfgOpts{'aggregation mode'} eq "none");
+ my $exifToolObj = shift;
+ my $counterSize = shift;
my $file;
my $info;
my $NewDir;
+ my $file_num = scalar(keys(%filenameshash));
+ my $file_rem = 0;
procmsg ("AGGREGATION\n");
procmsg ("===========\n");
- if ($configOptions{'aggregation mode'} eq "template") {
- dbgmsg (1, "aggregationProcess(): Template: $configOptions{'aggregation template'}\n");
+ if ($cfgOpts{'aggregation mode'} eq "template") {
+ dbgmsg (1, "aggregationProcess(): Template: $cfgOpts{'aggregation template'}\n");
my $fileCounter = $countStart;
foreach $file (sort (keys %filenameshash)) {
- dbgmsg (4, "aggregationProcess(): Processing file: $file\n");
- $info = $exifTool->ImageInfo($file);
- $NewDir = template2name($exifTool,
+ $file_rem++;
+ dbgmsg (4, "aggregationProcess(): Processing ($file_rem of $file_num) file: $file\n");
+ $info = $exifToolObj->ImageInfo($file);
+ $NewDir = template2name($exifToolObj,
$info,
- $configOptions{'aggregation template'},
+ $cfgOpts{'aggregation template'},
$fileCounter,
- $file);
+ $file,
+ $counterSize,
+ "0cw");
aggregateFile($file, $NewDir) if ($dryRun == 0);
- procmsg ("Aggregate: $file -> $NewDir\n", "\n");
+ procmsg ("Aggregate: ($file_rem of $file_num) $file -> $NewDir\n", "\n");
$fileCounter += $countStep;
}
- } elsif ($configOptions{'aggregation mode'} eq "delta") {
+ } elsif ($cfgOpts{'aggregation mode'} eq "delta") {
my $DirCounter = 1;
my $timestampPrev;
my $filePrev;
@@ -1060,27 +922,28 @@ sub aggregationProcess {
foreach $file (sort (keys %filenameshash)) {
$filetmp = $file;
- dbgmsg (4, "aggregationProcess(): Processing file: $file\n");
+ $file_rem++;
+ dbgmsg (4, "aggregationProcess(): Processing ($file_rem of $file_num) file: $file\n");
if ($DirCounter == 1) {
$timestampPrev = $filenameshash{$filetmp};
$filePrev = $filetmp;
- $NewDir = $configOptions{'aggregation directory'} . "." . sprintf($counterSize, $DirCounter);
+ $NewDir = $cfgOpts{'aggregation directory'} . "." . sprintf($counterSize, $DirCounter);
$DirCounter++;
aggregateFile($file, $NewDir) if ($dryRun == 0);
} else {
# Check for new direcroty creation
- if (($filenameshash{$filetmp} - $timestampPrev) > $configOptions{'aggregation delta'}) {
- $NewDir = $configOptions{'aggregation directory'} . "." . sprintf($counterSize, $DirCounter);
+ if (($filenameshash{$filetmp} - $timestampPrev) > $cfgOpts{'aggregation delta'}) {
+ $NewDir = $cfgOpts{'aggregation directory'} . "." . sprintf($counterSize, $DirCounter);
$DirCounter++;
}
aggregateFile($file, $NewDir) if ($dryRun == 0);
$timestampPrev = $filenameshash{$filetmp};
}
- procmsg ("Aggregate: $file -> $NewDir\n", "\n");
+ procmsg ("Aggregate: ($file_rem of $file_num) $file -> $NewDir\n", "\n");
}
} else {
- errmsg ("Aggregation mode $configOptions{'aggregation mode'} isn't implemented!\n");
+ errmsg ("Aggregation mode $cfgOpts{'aggregation mode'} isn't implemented!\n");
}
}
@@ -1103,13 +966,13 @@ sub aggregateFile {
my $file = shift;
my $NewDir = shift;
- if ($configOptions{'aggregation virtual'} == 0) {
+ if ($cfgOpts{'aggregation virtual'} == 0) {
makeDir($NewDir);
my $newfilename = $NewDir . "/" . $file;
rename ($file, $newfilename) || ( fatalmsg ("$file -> $newfilename\n"), die );
} else {
- makeDir($configOptions{'aggregation virtual directory'});
- $NewDir = $configOptions{'aggregation virtual directory'} . "/" . $NewDir;
+ makeDir($cfgOpts{'aggregation virtual directory'});
+ $NewDir = $cfgOpts{'aggregation virtual directory'} . "/" . $NewDir;
makeDir($NewDir);
my $newfilename = $NewDir . "/" . $file;
if (not -l $newfilename) {
@@ -1246,17 +1109,17 @@ sub rotateImg {
dbgmsg (3, "rotateImg(): $cmd\n");
system $cmd || ( fatalmsg ("System $cmd failed: $?\n"), die );
+ # preparing to write tags to the just rotated file
+ my $exifAfterRot = new Image::ExifTool;
+ $exifAfterRot->Options(Binary => 1);
+ $exifAfterRot->SetNewValuesFromFile($oldfile, '*:*');
+ $exifAfterRot->SetNewValue("Orientation", 1, Type => 'ValueConv');
+
if ($backup != 0) {
rename ($oldfile, $origfile) || ( fatalmsg ("$oldfile -> $origfile\n"), die );
}
rename ($newfile, $oldfile) || ( fatalmsg ("$newfile -> $oldfile\n"), die );
- # preparing to write Orientation tag to the just rotated file
- my $exifAfterRot = new Image::ExifTool;
- $exifAfterRot->Options(Binary => 1);
- $exifAfterRot->SetNewValuesFromFile($origfile, '*:*');
- $exifAfterRot->SetNewValue("Orientation", 1, Type => 'ValueConv');
-
# writing the changes to the EXIFs
exifWriter($exifAfterRot, $oldfile);
}
@@ -1295,7 +1158,7 @@ sub rotateThumbnail {
my $origThumb = ${$$infoObj{ThumbnailImage}};
- if ($configOptions{'use ipc'} == 0) {
+ if ($cfgOpts{'use ipc'} == 0) {
# extracting the thumbnail image
my $ThumbnailOriginal = $file . "_thumborig";
unless ( open ( OLDTHUMBNAIL, ">$ThumbnailOriginal" ) ) {
@@ -1406,7 +1269,6 @@ Tag writing options:
Colorizing options:
--use-color (*) colorized output
- --color <COLOR> ... setup color(s)
Misc options:
--dry-run show what would have been happened
@@ -1429,6 +1291,8 @@ sub template2name {
my $template = shift; # the template to be used
my $fileNo = shift; # counter for %c
my $fileName = shift; # file name for %n and %e
+ my $counterSize = shift;
+ my $angleSuffix = shift;# suffix to add to the end of the rotated files
my ($base, $ext); # file name %n and extension %e
if ($fileName =~ m/^(.*)\.([^\.]+)$/) {
@@ -1533,6 +1397,137 @@ sub template2name {
return $thename;
}
+########################################################################################
+#
+# MAIN() renames and rotates given files
+#
+
+getOptions();
+parseConfig($configFile);
+switchColor();
+
+# redefining options set in configuration file with set via CLI ones
+$cfgOpts{'aggregation delta'} = $aggrDelta if (defined $aggrDelta);
+$cfgOpts{'aggregation directory'} = $aggrDir if (defined $aggrDir);
+$cfgOpts{'aggregation mode'} = $aggrMode if (defined $aggrMode);
+$cfgOpts{'aggregation template'} = $aggrTemplate if (defined $aggrTemplate);
+$cfgOpts{'aggregation virtual'} = $aggrVirtual if (defined $aggrVirtual);
+$cfgOpts{'aggregation virtual directory'} = $aggrVirtDir if (defined $aggrVirtDir);
+$cfgOpts{'keywordize'} = $keywordize if (defined $keywordize);
+$cfgOpts{'keywords file'} = $keywordsFile if (defined $keywordsFile);
+$cfgOpts{'keywords replace'} = $keywordsReplace if (defined $keywordsReplace);
+$cfgOpts{'mtime'} = $mtime if (defined $mtime);
+$cfgOpts{'name template'} = $nameTemplate if (defined $nameTemplate);
+$cfgOpts{'trim'} = $trim if (defined $trim);
+$cfgOpts{'use color'} = $useColor if (defined $useColor);
+$cfgOpts{'use ipc'} = $useIPC if (defined $useIPC);
+
+dbgmsg (1, "main(): Show what would have been happened (no real actions).\n") if ($dryRun != 0);
+
+# Validate aggregation mode possible values
+if (not grep (/^$cfgOpts{'aggregation mode'}$/, ('none', 'delta', 'template'))) {
+ warnmsg ("Aggregation mode isn't correct!\n");
+}
+
+$cfgOpts{'aggregation directory'} = dirConv($cfgOpts{'aggregation directory'});
+$cfgOpts{'aggregation virtual directory'} = dirConv($cfgOpts{'aggregation virtual directory'});
+
+fatalmsg ("Current or multilevel directory isn't possible now, sorry. Check aggregation arguments.\n"), die
+ if ($cfgOpts{'aggregation mode'} ne "none" and
+ (dirValidator($cfgOpts{'aggregation directory'}) == 0 or
+ dirValidator($cfgOpts{'aggregation virtual directory'}) == 0));
+
+# Calculate ExifTool's verbosity
+my $exiftoolVerbose = ($verbose > $maxVerbosity) ? ($verbose - $maxVerbosity) : 0;
+
+# ExifTool object configuration
+my $exifTool = new Image::ExifTool;
+$exifTool->Options(Binary => 1, Unknown => 1, DateFormat => '%Y%m%d%H%M%S', Verbose => $exiftoolVerbose);
+
+chdir ($workDir) || ( fatalmsg ("Can't enter to $workDir!\n"), die );
+
+# All things in ARGV will be treated as file names to process
+@files = @ARGV;
+
+# if no file is given
+if (scalar(@files) == 0) {
+ opendir(DIR, "./") || ( fatalmsg ("Can't open $workDir!\n"), die );
+ my $file;
+ while ( defined ( $file = readdir DIR )) {
+ next if (not -f $file); # skip absent file or not a file
+ push (@files, $file) if (substr($file, length($file) - length($extToProcess)) eq $extToProcess);
+ }
+ closedir(DIR);
+}
+
+# independently of @files initialization doing this
+my @filenames;
+
+foreach my $file ( @files ) {
+ next if (not -f $file); # skip absent file or not a file
+ next if (grep {/^$file$/} @excludeList); # skip excluded file
+ push (@filenames, $file);
+}
+
+# No file to process?
+if (scalar(@filenames) == 0) {
+ fatalmsg ("No files to process!\n");
+ exit 1;
+}
+
+# Parse configuration file tag set
+foreach my $cKey (keys %cfgOpts) {
+ next if ($cKey !~ m/^tag(file)?#\d+#\d+$/); # skip not a tag or tagfile
+ my %tag = strToHash($cfgOpts{$cKey});
+ foreach my $key (keys %tag) {
+ $tags{$key} = $tag{$key};
+ if ($cKey =~ m/^tagfile/) {
+ dbgmsg (4, "main(): Read data from '$tags{$key}{value}' for '$key'\n");
+ $tags{$key}{value} = getFileData($tags{$key}{value});
+ }
+ }
+}
+
+# Put command line arguments to appropriate tags
+$tags{'Comment'} = {value => getFileData($comfile)} if (defined $comfile);
+$tags{'UserComment'} = {value => $userComment} if (defined $userComment);
+
+# Merge tags from configuration file with command line arguments
+map { $tags{$_} = $tagsFromCli{$_} } keys %tagsFromCli;
+
+# Print parsed tags at debug level
+my @dbgTags;
+foreach my $key (sort (keys %tags)) {
+ my $group = defined $tags{$key}{group} ? $tags{$key}{group} : "";
+ my $value = defined $tags{$key}{value} ? $tags{$key}{value} : "";
+ push (@dbgTags, "$key [$group] = $value");
+}
+dbgmsg (4, "Tags:\n", join("\n", @dbgTags), "\n") if (scalar(@dbgTags) > 0);
+
+# Validate angle value
+if ((defined $rotateAngle and not grep(/^$rotateAngle$/, keys %rotangles)) or
+ (defined $rotateThumbnail and not grep(/^$rotateThumbnail$/, keys %rotangles))) {
+ fatalmsg ("Angle should be 90, 180 or 270!\n");
+ exit 1;
+}
+
+@files = sort @filenames;
+dbgmsg (4, "main(): Pushed files(", scalar(@files), "):\n", join("\n", @files), "\n");
+
+# Preparing the variable, which contains the format of the counter output
+my $counterSize;
+
+if ($countFF != 0) {
+ my $size = length((scalar(@filenames) - 1) * $countStep + $countStart);
+ $counterSize = "%." . $size . "d";
+ dbgmsg (1, "main(): Counter size: $size (amount files in cache: ", scalar(@filenames), ")\n");
+} else {
+ $counterSize = "%d";
+}
+
+renRotProcess($exifTool, $counterSize);
+aggregationProcess($exifTool, $counterSize);
+
__END__
=head1 NAME
@@ -1786,10 +1781,6 @@ no tags will be written. Default is to write tags.
colorized output. This NOT works under Win32.
-=item B<--color> I<COLOR>
-
-setup color for choosen facility
-
=item B<--dry-run>
show what would have been happened (no real actions)

Return to:

Send suggestions and report system problems to the System administrator.