exiftool-vendored.pl 12.56.0 → 12.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/bin/Changes +80 -5
  2. package/bin/MANIFEST +4 -0
  3. package/bin/META.json +1 -1
  4. package/bin/META.yml +1 -1
  5. package/bin/README +2 -2
  6. package/bin/config_files/example.config +1 -0
  7. package/bin/config_files/rotate_regions.config +1 -1
  8. package/bin/exiftool +174 -99
  9. package/bin/lib/Image/ExifTool/AIFF.pm +2 -2
  10. package/bin/lib/Image/ExifTool/APE.pm +2 -2
  11. package/bin/lib/Image/ExifTool/BuildTagLookup.pm +19 -15
  12. package/bin/lib/Image/ExifTool/Canon.pm +26 -6
  13. package/bin/lib/Image/ExifTool/CanonRaw.pm +5 -1
  14. package/bin/lib/Image/ExifTool/DJI.pm +28 -2
  15. package/bin/lib/Image/ExifTool/Exif.pm +77 -19
  16. package/bin/lib/Image/ExifTool/FlashPix.pm +32 -10
  17. package/bin/lib/Image/ExifTool/FujiFilm.pm +7 -3
  18. package/bin/lib/Image/ExifTool/GPS.pm +7 -2
  19. package/bin/lib/Image/ExifTool/Geotag.pm +30 -7
  20. package/bin/lib/Image/ExifTool/JPEG.pm +14 -2
  21. package/bin/lib/Image/ExifTool/Jpeg2000.pm +5 -5
  22. package/bin/lib/Image/ExifTool/LIF.pm +10 -2
  23. package/bin/lib/Image/ExifTool/LNK.pm +5 -4
  24. package/bin/lib/Image/ExifTool/MIE.pm +3 -3
  25. package/bin/lib/Image/ExifTool/MPEG.pm +2 -2
  26. package/bin/lib/Image/ExifTool/MakerNotes.pm +3 -2
  27. package/bin/lib/Image/ExifTool/Minolta.pm +6 -7
  28. package/bin/lib/Image/ExifTool/MinoltaRaw.pm +2 -1
  29. package/bin/lib/Image/ExifTool/Nikon.pm +1003 -907
  30. package/bin/lib/Image/ExifTool/NikonCustom.pm +2 -2
  31. package/bin/lib/Image/ExifTool/NikonSettings.pm +1 -1
  32. package/bin/lib/Image/ExifTool/Olympus.pm +88 -6
  33. package/bin/lib/Image/ExifTool/PNG.pm +10 -2
  34. package/bin/lib/Image/ExifTool/PanasonicRaw.pm +27 -1
  35. package/bin/lib/Image/ExifTool/Pentax.pm +8 -5
  36. package/bin/lib/Image/ExifTool/PhaseOne.pm +14 -1
  37. package/bin/lib/Image/ExifTool/Photoshop.pm +38 -7
  38. package/bin/lib/Image/ExifTool/QuickTime.pm +44 -13
  39. package/bin/lib/Image/ExifTool/QuickTimeStream.pl +40 -6
  40. package/bin/lib/Image/ExifTool/README +19 -2
  41. package/bin/lib/Image/ExifTool/RIFF.pm +34 -13
  42. package/bin/lib/Image/ExifTool/Rawzor.pm +2 -2
  43. package/bin/lib/Image/ExifTool/Ricoh.pm +2 -1
  44. package/bin/lib/Image/ExifTool/Sigma.pm +5 -4
  45. package/bin/lib/Image/ExifTool/SigmaRaw.pm +9 -3
  46. package/bin/lib/Image/ExifTool/Sony.pm +24 -1
  47. package/bin/lib/Image/ExifTool/TagLookup.pm +4678 -4628
  48. package/bin/lib/Image/ExifTool/TagNames.pod +305 -113
  49. package/bin/lib/Image/ExifTool/Validate.pm +5 -5
  50. package/bin/lib/Image/ExifTool/WriteExif.pl +42 -0
  51. package/bin/lib/Image/ExifTool/WriteXMP.pl +1 -1
  52. package/bin/lib/Image/ExifTool/Writer.pl +150 -36
  53. package/bin/lib/Image/ExifTool/XMP.pm +19 -4
  54. package/bin/lib/Image/ExifTool/XMP2.pl +2 -1
  55. package/bin/lib/Image/ExifTool.pm +195 -42
  56. package/bin/lib/Image/ExifTool.pod +44 -9
  57. package/bin/perl-Image-ExifTool.spec +1 -1
  58. package/bin/pp_build_exe.args +4 -4
  59. package/package.json +3 -3
package/bin/exiftool CHANGED
@@ -11,7 +11,7 @@ use strict;
11
11
  use warnings;
12
12
  require 5.004;
13
13
 
14
- my $version = '12.56';
14
+ my $version = '12.60';
15
15
 
16
16
  # add our 'lib' directory to the include list BEFORE 'use Image::ExifTool'
17
17
  BEGIN {
@@ -77,6 +77,7 @@ sub AcceptFile($);
77
77
  sub SlurpFile($$);
78
78
  sub FilterArgfileLine($);
79
79
  sub ReadStayOpen($);
80
+ sub Progress($$);
80
81
  sub PrintTagList($@);
81
82
  sub PrintErrors($$$);
82
83
 
@@ -102,6 +103,7 @@ my @newValues; # list of new tag values to set
102
103
  my @requestTags; # tags to request (for -p or -if option arguments)
103
104
  my @srcFmt; # source file name format strings
104
105
  my @tags; # list of tags to extract
106
+ my %altFile; # alternate files to extract information (keyed by lower-case family 8 group)
105
107
  my %appended; # list of files appended to
106
108
  my %countLink; # count hard and symbolic links made
107
109
  my %created; # list of files we created
@@ -114,6 +116,7 @@ my %outComma; # flag that output text file needs a comma
114
116
  my %outTrailer; # trailer for output text file
115
117
  my %preserveTime; # preserved timestamps for files
116
118
  my %printFmt; # the contents of the print format file
119
+ my %seqFileDir; # file sequence number in each directory
117
120
  my %setTags; # hash of list references for tags to set from files
118
121
  my %setTagsList; # list of other tag lists for multiple -tagsFromFile from the same file
119
122
  my %usedFileName; # lookup for file names we already used in TestName feature
@@ -182,7 +185,9 @@ my $pause; # pause before returning
182
185
  my $preserveTime; # flag to preserve times of updated files (2=preserve FileCreateDate only)
183
186
  my $progress; # flag to calculate total files to process (0=calculate but don't display)
184
187
  my $progressCount; # count of files processed
188
+ my $progressIncr; # increment for progress counter
185
189
  my $progressMax; # total number of files to process
190
+ my $progressNext; # next progress count to output
186
191
  my $progStr; # progress message string
187
192
  my $quiet; # flag to disable printing of informational messages / warnings
188
193
  my $rafStdin; # File::RandomAccess for stdin (if necessary to rewind)
@@ -193,7 +198,7 @@ my $saveCount; # count the number of times we will/did call SaveNewValues()
193
198
  my $scanWritable; # flag to process only writable file types
194
199
  my $sectHeader; # current section header for -p option
195
200
  my $sectTrailer; # section trailer for -p option
196
- my $seqFileBase; # sequential file number at start of directory
201
+ my $seqFileDir; # sequential file number used for %-C
197
202
  my $seqFileNum; # sequential file number used for %C
198
203
  my $setCharset; # character set setting ('default' if not set and -csv -b used)
199
204
  my $showGroup; # number of group to show (may be zero or '')
@@ -211,6 +216,7 @@ my $validFile; # flag indicating we processed a valid file
211
216
  my $verbose; # verbose setting
212
217
  my $vout; # verbose output file reference (\*STDOUT or \*STDERR)
213
218
  my $windowTitle; # title for console window
219
+ my %wroteHEAD; # list of output txt files to which we wrote HEAD
214
220
  my $xml; # flag for XML-formatted output
215
221
 
216
222
  # flag to keep the input -@ argfile open:
@@ -251,17 +257,15 @@ my %optArgs = (
251
257
  '-csvdelim' => 1,
252
258
  '-d' => 1, '-dateformat' => 1,
253
259
  '-D' => 0, # necessary to avoid matching lower-case equivalent
254
- '-echo' => 1, '-echo1' => 1, '-echo2' => 1, '-echo3' => 1, '-echo4' => 1,
255
- '-efile' => 1, '-efile1' => 1, '-efile2' => 1, '-efile3' => 1, '-efile4' => 1,
256
- '-efile!' => 1, '-efile1!' => 1, '-efile2!' => 1, '-efile3!' => 1, '-efile4!' => 1,
260
+ '-echo' => 1, '-echo#' => 1,
261
+ '-efile' => 1, '-efile#' => 1, '-efile!' => 1, '-efile#!' => 1,
257
262
  '-ext' => 1, '--ext' => 1, '-ext+' => 1, '--ext+' => 1,
258
263
  '-extension' => 1, '--extension' => 1, '-extension+' => 1, '--extension+' => 1,
259
- '-fileorder' => 1, '-fileorder0' => 1, '-fileorder1' => 1, '-fileorder2' => 1,
260
- '-fileorder3' => 1, '-fileorder4' => 1, '-fileorder5' => 1,
264
+ '-fileorder' => 1, '-fileorder#' => 1,
261
265
  '-geotag' => 1,
262
266
  '-globaltimeshift' => 1,
263
267
  '-i' => 1, '-ignore' => 1,
264
- '-if' => 1, '-if0' => 1, '-if1' => 1, '-if2' => 1, '-if3' => 1, '-if4' => 1, '-if5' => 1,
268
+ '-if' => 1, '-if#' => 1,
265
269
  '-lang' => 0, # (optional arg; cannot begin with "-")
266
270
  '-listitem' => 1,
267
271
  '-o' => 1, '-out' => 1,
@@ -448,6 +452,7 @@ undef %outComma;
448
452
  undef %outTrailer;
449
453
  undef %printFmt;
450
454
  undef %preserveTime;
455
+ undef %seqFileDir;
451
456
  undef %setTags;
452
457
  undef %setTagsList;
453
458
  undef %usedFileName;
@@ -489,7 +494,9 @@ undef $outOpt;
489
494
  undef $preserveTime;
490
495
  undef $progress;
491
496
  undef $progressCount;
497
+ undef $progressIncr;
492
498
  undef $progressMax;
499
+ undef $progressNext;
493
500
  undef $recurse;
494
501
  undef $scanWritable;
495
502
  undef $sectHeader;
@@ -532,7 +539,7 @@ $quiet = 0;
532
539
  $rtnVal = 0;
533
540
  $saveCount = 0;
534
541
  $sectTrailer = '';
535
- $seqFileBase = 0;
542
+ $seqFileDir = 0;
536
543
  $seqFileNum = 0;
537
544
  $tabFormat = 0;
538
545
  $vout = \*STDOUT;
@@ -915,12 +922,14 @@ for (;;) {
915
922
  $mt->Options(Duplicates => 1);
916
923
  next;
917
924
  }
918
- if (/^efile(\d)?(!)?$/i) {
925
+ if (/^efile(\d+)?(!)?$/i) {
919
926
  my $arg = shift;
920
927
  defined $arg or Error("Expecting file name for -$_ option\n"), $badCmd=1, next;
921
- $efile[0] = $arg if not $1 or $1 & 0x01;
922
- $efile[1] = $arg if $1 and $1 & 0x02;
923
- $efile[2] = $arg if $1 and $1 & 0x04;
928
+ $efile[0] = $arg if not $1 or $1 & 0x01;# error
929
+ $efile[1] = $arg if $1 and $1 & 0x02; # unchanged
930
+ $efile[2] = $arg if $1 and $1 & 0x04; # failed -if condition
931
+ $efile[3] = $arg if $1 and $1 & 0x08; # updated
932
+ $efile[4] = $arg if $1 and $1 & 0x016; # created
924
933
  unlink $arg if $2;
925
934
  next;
926
935
  }
@@ -946,6 +955,10 @@ for (;;) {
946
955
  $mt->Options(FastScan => (length $1 ? $1 : 1));
947
956
  next;
948
957
  }
958
+ if (/^(file\d+)$/i) {
959
+ $altFile{lc $1} = shift or Error("Expecting file name for -file option\n"), $badCmd=1, next;
960
+ next;
961
+ }
949
962
  if (/^fileorder(\d*)$/i) {
950
963
  push @fileOrder, shift if @ARGV;
951
964
  my $num = $1 || 0;
@@ -1119,9 +1132,11 @@ for (;;) {
1119
1132
  }
1120
1133
  (/^P$/ or $a eq 'preserve') and $preserveTime = 1, next;
1121
1134
  /^password$/i and $mt->Options(Password => shift), next;
1122
- if (/^progress(:.*)?$/i) {
1123
- if ($1) {
1124
- $windowTitle = substr $1, 1;
1135
+ if (/^progress(\d*)(:.*)?$/i) {
1136
+ $progressIncr = $1 || 1;
1137
+ $progressNext = 0; # start showing progress at the first file
1138
+ if ($2) {
1139
+ $windowTitle = substr $2, 1;
1125
1140
  $windowTitle = 'ExifTool %p%%' unless length $windowTitle;
1126
1141
  $windowTitle =~ /%\d*[bpr]/ and $progress = 0 unless defined $progress;
1127
1142
  } else {
@@ -1239,7 +1254,8 @@ for (;;) {
1239
1254
  next;
1240
1255
  }
1241
1256
  if (/^(w|textout|tagout)([!+]*)$/i) {
1242
- $textOut = shift || Warn("Expecting output extension for -$_ option\n");
1257
+ # (note: all logic ignores $textOut of 0 or '')
1258
+ $textOut = shift || Warn("Expecting argument for -$_ option\n");
1243
1259
  my ($t1, $t2) = ($1, $2);
1244
1260
  $textOverwrite = 0;
1245
1261
  $textOverwrite += 1 if $t2 =~ /!/; # overwrite
@@ -1323,7 +1339,7 @@ for (;;) {
1323
1339
  AddSetTagsFile($setTagsFile = '@') if not $setTagsFile and /(<|>)/;
1324
1340
  if ($setTagsFile) {
1325
1341
  push @{$setTags{$setTagsFile}}, $_;
1326
- if (/>/) {
1342
+ if ($1 eq '>') {
1327
1343
  $useMWG = 1 if /^(.*>\s*)?mwg:/si;
1328
1344
  if (/\b(filename|directory|testname)#?$/i) {
1329
1345
  $doSetFileName = 1;
@@ -1711,7 +1727,7 @@ if (defined $showGroup and not (@tags and $allGroup) and ($sortOpt or not define
1711
1727
  $mt->Options(Sort => "Group$showGroup");
1712
1728
  }
1713
1729
 
1714
- if (defined $textOut) {
1730
+ if ($textOut) {
1715
1731
  CleanFilename($textOut); # make all forward slashes
1716
1732
  # add '.' before output extension if necessary
1717
1733
  $textOut = ".$textOut" unless $textOut =~ /[.%]/ or defined $tagOut;
@@ -1932,10 +1948,10 @@ Exit $rtnValApp; # all done
1932
1948
  sub GetImageInfo($$)
1933
1949
  {
1934
1950
  my ($et, $orig) = @_;
1935
- my (@foundTags, $info, $file, $ind);
1951
+ my (@foundTags, $info, $file, $ind, $g8);
1936
1952
 
1937
1953
  # set window title for this file if necessary
1938
- if (defined $windowTitle) {
1954
+ if (defined $windowTitle and $progressCount >= $progressNext) {
1939
1955
  my $prog = $progressMax ? "$progressCount/$progressMax" : '0/0';
1940
1956
  my $title = $windowTitle;
1941
1957
  my ($num, $denom) = split '/', $prog;
@@ -1951,6 +1967,7 @@ sub GetImageInfo($$)
1951
1967
  );
1952
1968
  $title =~ s/%([%bfpr])/$lkup{$1}/eg;
1953
1969
  SetWindowTitle($title);
1970
+ undef $progressNext;
1954
1971
  }
1955
1972
  unless (length $orig or $outOpt) {
1956
1973
  Warn qq(Error: Zero-length file name - ""\n);
@@ -1974,6 +1991,11 @@ sub GetImageInfo($$)
1974
1991
  } else {
1975
1992
  $file = $orig;
1976
1993
  }
1994
+ # set alternate file names
1995
+ foreach $g8 (sort keys %altFile) {
1996
+ my $altName = FilenameSPrintf($altFile{$g8}, $orig);
1997
+ $et->SetAlternateFile($g8, $altName);
1998
+ }
1977
1999
 
1978
2000
  my $pipe = $file;
1979
2001
  if ($doUnzip) {
@@ -2044,7 +2066,7 @@ sub GetImageInfo($$)
2044
2066
  undef @foundTags if $fastCondition; # ignore if we didn't get all tags
2045
2067
  }
2046
2068
  unless ($result) {
2047
- $verbose and print $vout "-------- $file (failed condition)$progStr\n";
2069
+ Progress($vout, "-------- $file (failed condition)") if $verbose;
2048
2070
  EFile($file, 2);
2049
2071
  ++$countFailed;
2050
2072
  return;
@@ -2054,7 +2076,7 @@ sub GetImageInfo($$)
2054
2076
  undef $info if $verbose or defined $fastCondition;
2055
2077
  }
2056
2078
  if (defined $deleteOrig) {
2057
- print $vout "======== $file$progStr\n" if defined $verbose;
2079
+ Progress($vout, "======== $file") if defined $verbose;
2058
2080
  ++$count;
2059
2081
  my $original = "${file}_original";
2060
2082
  $et->Exists($original) or return;
@@ -2063,6 +2085,7 @@ sub GetImageInfo($$)
2063
2085
  push @delFiles, $original;
2064
2086
  } elsif ($et->Rename($original, $file)) {
2065
2087
  $verbose and print $vout "Restored from $original\n";
2088
+ EFile($file, 3);
2066
2089
  ++$countGoodWr;
2067
2090
  } else {
2068
2091
  Warn "Error renaming $original\n";
@@ -2072,6 +2095,8 @@ sub GetImageInfo($$)
2072
2095
  return;
2073
2096
  }
2074
2097
  ++$seqFileNum; # increment our file counter
2098
+ my ($dir) = Image::ExifTool::SplitFileName($orig);
2099
+ $seqFileDir = $seqFileDir{$dir} = ($seqFileDir{$dir} || 0) + 1;
2075
2100
 
2076
2101
  my $lineCount = 0;
2077
2102
  my ($fp, $outfile, $append);
@@ -2084,12 +2109,12 @@ sub GetImageInfo($$)
2084
2109
  }
2085
2110
 
2086
2111
  if ($isWriting) {
2087
- print $vout "======== $file$progStr\n" if defined $verbose;
2112
+ Progress($vout, "======== $file") if defined $verbose;
2088
2113
  SetImageInfo($et, $file, $orig);
2089
2114
  $info = $et->GetInfo('Warning', 'Error');
2090
2115
  PrintErrors($et, $info, $file);
2091
2116
  # close output text file if necessary
2092
- if ($outfile) {
2117
+ if (defined $outfile) {
2093
2118
  undef $tmpText;
2094
2119
  close($fp);
2095
2120
  $et->Options(TextOut => $vout);
@@ -2108,7 +2133,7 @@ sub GetImageInfo($$)
2108
2133
  unless ($file eq '-' or $et->Exists($file)) {
2109
2134
  Warn "Error: File not found - $file\n";
2110
2135
  FileNotFound($file);
2111
- $outfile and close($fp), undef($tmpText), $et->Unlink($outfile);
2136
+ defined $outfile and close($fp), undef($tmpText), $et->Unlink($outfile);
2112
2137
  EFile($file);
2113
2138
  ++$countBad;
2114
2139
  return;
@@ -2125,7 +2150,7 @@ sub GetImageInfo($$)
2125
2150
  }
2126
2151
  }
2127
2152
  $o = \*STDERR if $progress and not $o;
2128
- $o and print $o "======== $file$progStr\n";
2153
+ Progress($o, "======== $file") if $o;
2129
2154
  if ($info) {
2130
2155
  # get the information we wanted
2131
2156
  if (@tags and not %printFmt) {
@@ -2147,7 +2172,7 @@ sub GetImageInfo($$)
2147
2172
  }
2148
2173
  # all done now if we already wrote output text file (eg. verbose option)
2149
2174
  if ($fp) {
2150
- if ($outfile) {
2175
+ if (defined $outfile) {
2151
2176
  $et->Options(TextOut => \*STDOUT);
2152
2177
  undef $tmpText;
2153
2178
  if ($info->{Error}) {
@@ -2176,7 +2201,7 @@ sub GetImageInfo($$)
2176
2201
  }
2177
2202
 
2178
2203
  # open output file (or stdout if no output file) if not done already
2179
- unless ($outfile or $tagOut) {
2204
+ unless (defined $outfile or $tagOut) {
2180
2205
  ($fp, $outfile, $append) = OpenOutputFile($orig);
2181
2206
  $fp or EFile($file), ++$countBad, return;
2182
2207
  $tmpText = $outfile unless $append;
@@ -2201,6 +2226,10 @@ sub GetImageInfo($$)
2201
2226
  my $skipBody;
2202
2227
  foreach $type (qw(HEAD SECT IF BODY ENDS TAIL)) {
2203
2228
  my $prf = $printFmt{$type} or next;
2229
+ if ($type eq 'HEAD' and defined $outfile) {
2230
+ next if $wroteHEAD{$outfile};
2231
+ $wroteHEAD{$outfile} = 1;
2232
+ }
2204
2233
  next if $type eq 'BODY' and $skipBody;
2205
2234
  if ($lastDoc) {
2206
2235
  if ($doc) {
@@ -2238,7 +2267,7 @@ sub GetImageInfo($$)
2238
2267
  }
2239
2268
  }
2240
2269
  }
2241
- delete $printFmt{HEAD} unless $outfile; # print header only once per output file
2270
+ delete $printFmt{HEAD} unless defined $outfile; # print header only once per output file
2242
2271
  my $errs = $et->GetInfo('Warning', 'Error');
2243
2272
  PrintErrors($et, $errs, $file) and EFile($file);
2244
2273
  } elsif (not $disableOutput) {
@@ -2394,7 +2423,7 @@ TAG: foreach $tag (@foundTags) {
2394
2423
  next TAG;
2395
2424
  }
2396
2425
  my @groups = $et->GetGroup($tag);
2397
- $outfile and close($fp), undef($tmpText); # (shouldn't happen)
2426
+ defined $outfile and close($fp), undef($tmpText); # (shouldn't happen)
2398
2427
  my $org = $et->GetValue('OriginalRawFileName') || $et->GetValue('OriginalFileName');
2399
2428
  ($fp, $outfile, $append) = OpenOutputFile($orig, $tagName, \@groups, $ext, $org);
2400
2429
  $fp or ++$countBad, next TAG;
@@ -2700,7 +2729,7 @@ TAG: foreach $tag (@foundTags) {
2700
2729
  }
2701
2730
  }
2702
2731
  }
2703
- if ($outfile) {
2732
+ if (defined $outfile) {
2704
2733
  if ($textOverwrite & 0x02) {
2705
2734
  # save state of this file if we may be appending
2706
2735
  $outComma{$outfile} = $comma;
@@ -3016,6 +3045,7 @@ sub SetImageInfo($$$)
3016
3045
  $r3 = $et->SetSystemTags($file);
3017
3046
  }
3018
3047
  if ($r0 > 0 or $r1 > 0 or $r2 > 0 or $r3 > 0) {
3048
+ EFile($infile, 3);
3019
3049
  ++$countGoodWr;
3020
3050
  } elsif ($r0 < 0 or $r1 < 0 or $r2 < 0 or $r3 < 0) {
3021
3051
  EFile($infile);
@@ -3130,6 +3160,7 @@ sub SetImageInfo($$$)
3130
3160
  $preserveTime{$file} = [ $aTime, $mTime, $cTime ];
3131
3161
  }
3132
3162
  }
3163
+ EFile($infile, 3);
3133
3164
  ++$countGoodWr;
3134
3165
  } else {
3135
3166
  close(NEW_FILE);
@@ -3145,6 +3176,7 @@ sub SetImageInfo($$$)
3145
3176
  # simply rename temporary file to replace original
3146
3177
  # (if we didn't already rename it to add "_original")
3147
3178
  } elsif ($et->Rename($tmpFile, $dstFile)) {
3179
+ EFile($infile, 3);
3148
3180
  ++$countGoodWr;
3149
3181
  } else {
3150
3182
  my $newFile = $tmpFile;
@@ -3162,21 +3194,26 @@ sub SetImageInfo($$$)
3162
3194
  # (don't delete tmp file now because it is all we have left)
3163
3195
  ++$countBadWr;
3164
3196
  } else {
3197
+ EFile($infile, 3);
3165
3198
  ++$countGoodWr;
3166
3199
  }
3167
3200
  }
3168
3201
  } elsif ($overwriteOrig) {
3169
3202
  # erase original file
3203
+ EFile($infile, 3);
3170
3204
  $et->Unlink($file) or Warn "Error erasing original $file\n";
3171
3205
  ++$countGoodWr;
3172
3206
  } else {
3207
+ EFile($infile, 4);
3173
3208
  ++$countGoodCr;
3174
3209
  }
3175
3210
  } else {
3176
3211
  # this file was created from scratch, not edited
3212
+ EFile($infile, 4);
3177
3213
  ++$countGoodCr;
3178
3214
  }
3179
3215
  } else {
3216
+ EFile($infile, 3);
3180
3217
  ++$countGoodWr;
3181
3218
  }
3182
3219
  } elsif ($success) {
@@ -3661,8 +3698,19 @@ sub ProcessFiles($;$)
3661
3698
  foreach $file (@files) {
3662
3699
  $et->Options(CharsetFileName => 'UTF8') if $utf8FileName{$file};
3663
3700
  if (defined $progressMax) {
3701
+ unless (defined $progressNext) {
3702
+ $progressNext = $progressCount + $progressIncr;
3703
+ $progressNext -= $progressNext % $progressIncr;
3704
+ $progressNext = $progressMax if $progressNext > $progressMax;
3705
+ }
3664
3706
  ++$progressCount;
3665
- $progStr = " [$progressCount/$progressMax]" if $progress;
3707
+ if ($progress) {
3708
+ if ($progressCount >= $progressNext) {
3709
+ $progStr = " [$progressCount/$progressMax]";
3710
+ } else {
3711
+ undef $progStr; # don't update progress yet
3712
+ }
3713
+ }
3666
3714
  }
3667
3715
  if ($et->IsDirectory($file) and not $listDir) {
3668
3716
  $multiFile = $validFile = 1;
@@ -3670,7 +3718,7 @@ sub ProcessFiles($;$)
3670
3718
  } elsif ($filterFlag and not AcceptFile($file)) {
3671
3719
  if ($et->Exists($file)) {
3672
3720
  $filtered = 1;
3673
- $verbose and print $vout "-------- $file (wrong extension)$progStr\n";
3721
+ Progress($vout, "-------- $file (wrong extension)") if $verbose;
3674
3722
  } else {
3675
3723
  Warn "Error: File not found - $file\n";
3676
3724
  FileNotFound($file);
@@ -3718,8 +3766,6 @@ sub ScanDir($$;$)
3718
3766
  $utf8Name = 1;
3719
3767
  }
3720
3768
  return if $ignore{$dir};
3721
- my $oldBase = $seqFileBase;
3722
- $seqFileBase = $seqFileNum;
3723
3769
  # use Win32::FindFile on Windows if available
3724
3770
  # (ReadDir will croak if there is a wildcard, so check for this)
3725
3771
  if ($^O eq 'MSWin32' and $dir !~ /[*?]/) {
@@ -3751,7 +3797,6 @@ sub ScanDir($$;$)
3751
3797
  # use standard perl library routines to read directory
3752
3798
  unless (opendir(DIR_HANDLE, $dir)) {
3753
3799
  Warn("Error opening directory $dir\n");
3754
- $seqFileBase = $oldBase + ($seqFileNum - $seqFileBase);
3755
3800
  return;
3756
3801
  }
3757
3802
  @fileList = readdir(DIR_HANDLE);
@@ -3831,8 +3876,6 @@ sub ScanDir($$;$)
3831
3876
  }
3832
3877
  ++$countDir;
3833
3878
  $et->Options(CharsetFileName => $enc); # restore original setting
3834
- # update sequential file base for parent directory
3835
- $seqFileBase = $oldBase + ($seqFileNum - $seqFileBase);
3836
3879
  }
3837
3880
 
3838
3881
  #------------------------------------------------------------------------------
@@ -4128,16 +4171,15 @@ sub NextUnusedFilename($;$)
4128
4171
  return $fmt unless $fmt =~ /%[-+]?\d*\.?\d*[lun]?[cC]/;
4129
4172
  my %sep = ( '-' => '-', '+' => '_' );
4130
4173
  my ($copy, $alpha) = (0, 'a');
4131
- my $seq = $seqFileNum - 1;
4132
4174
  for (;;) {
4133
4175
  my ($filename, $pos) = ('', 0);
4134
4176
  while ($fmt =~ /(%([-+]?)(\d*)(\.?)(\d*)([lun]?)([cC]))/g) {
4135
4177
  $filename .= substr($fmt, $pos, pos($fmt) - $pos - length($1));
4136
4178
  $pos = pos($fmt);
4137
4179
  my ($sign, $wid, $dec, $wid2, $mod, $tok) = ($2, $3 || 0, $4, $5 || 0, $6, $7);
4138
- my $diff;
4180
+ my $seq;
4139
4181
  if ($tok eq 'C') {
4140
- $diff = $wid - ($sign eq '-' ? $seqFileBase : 0);
4182
+ $seq = $wid + ($sign eq '-' ? $seqFileDir : $seqFileNum) - 1;
4141
4183
  $wid = $wid2;
4142
4184
  } else {
4143
4185
  next unless $dec or $copy;
@@ -4146,13 +4188,13 @@ sub NextUnusedFilename($;$)
4146
4188
  $filename .= $sep{$sign} if $sign;
4147
4189
  }
4148
4190
  if ($mod and $mod ne 'n') {
4149
- my $a = $tok eq 'C' ? Num2Alpha($diff + $seq) : $alpha;
4191
+ my $a = $tok eq 'C' ? Num2Alpha($seq) : $alpha;
4150
4192
  my $str = ($wid and $wid > length $a) ? 'a' x ($wid - length($a)) : '';
4151
4193
  $str .= $a;
4152
4194
  $str = uc $str if $mod eq 'u';
4153
4195
  $filename .= $str;
4154
4196
  } else {
4155
- my $c = $tok eq 'C' ? ($diff + $seq) : $copy;
4197
+ my $c = $tok eq 'C' ? $seq : $copy;
4156
4198
  my $num = $c + ($mod ? 1 : 0);
4157
4199
  $filename .= $wid ? sprintf("%.${wid}d",$num) : $num;
4158
4200
  }
@@ -4167,7 +4209,6 @@ sub NextUnusedFilename($;$)
4167
4209
  }
4168
4210
  ++$copy;
4169
4211
  ++$alpha;
4170
- ++$seq;
4171
4212
  }
4172
4213
  }
4173
4214
 
@@ -4373,9 +4414,13 @@ sub ReadStayOpen($)
4373
4414
  undef $optArgs;
4374
4415
  next unless $lastOpt eq '-stay_open' or $lastOpt eq '-@';
4375
4416
  } else {
4376
- $optArgs = $optArgs{$arg};
4377
4417
  $lastOpt = lc $arg;
4378
- $optArgs = $optArgs{$lastOpt} unless defined $optArgs;
4418
+ $optArgs = $optArgs{$arg};
4419
+ unless (defined $optArgs) {
4420
+ $optArgs = $optArgs{$lastOpt};
4421
+ # handle options with trailing numbers
4422
+ $optArgs = $optArgs{"$1#$2"} if not defined $optArgs and $lastOpt =~ /^(.*?)\d+(!?)$/;
4423
+ }
4379
4424
  next unless $lastOpt =~ /^-execute\d*$/;
4380
4425
  }
4381
4426
  $processArgs = 1;
@@ -4405,7 +4450,7 @@ sub ReadStayOpen($)
4405
4450
 
4406
4451
  #------------------------------------------------------------------------------
4407
4452
  # Add new entry to -efile output file
4408
- # Inputs: 0) file name, 1) -efile option number (0=error, 1=same, 2=failed)
4453
+ # Inputs: 0) file name, 1) -efile option number (0=error, 1=same, 2=failed, 3=updated, 4=created)
4409
4454
  sub EFile($$)
4410
4455
  {
4411
4456
  my $entry = shift;
@@ -4426,6 +4471,18 @@ sub EFile($$)
4426
4471
  }
4427
4472
  }
4428
4473
 
4474
+ #------------------------------------------------------------------------------
4475
+ # Print progress message if it is time for it
4476
+ # Inputs: 0) file ref, 1) message
4477
+ sub Progress($$)
4478
+ {
4479
+ my ($file, $msg) = @_;
4480
+ if (defined $progStr) {
4481
+ print $file $msg, $progStr, "\n";
4482
+ undef $progressNext;
4483
+ }
4484
+ }
4485
+
4429
4486
  #------------------------------------------------------------------------------
4430
4487
  # Print list of tags
4431
4488
  # Inputs: 0) message, 1-N) list of tag names
@@ -4672,7 +4729,7 @@ L<Processing control|/Processing control>
4672
4729
  -overwrite_original_in_place Overwrite original by copying tmp file
4673
4730
  -P (-preserve) Preserve file modification date/time
4674
4731
  -password PASSWD Password for processing protected files
4675
- -progress[:[TITLE]] Show file progress count
4732
+ -progress[NUM][:[TITLE]] Show file progress count
4676
4733
  -q (-quiet) Quiet processing
4677
4734
  -r[.] (-recurse) Recursively process subdirectories
4678
4735
  -scanForXMP Brute force XMP scan
@@ -4708,6 +4765,7 @@ L<Advanced options|/Advanced options>
4708
4765
  -echo[NUM] TEXT Echo text to stdout or stderr
4709
4766
  -efile[NUM][!] ERRFILE Save names of files with errors
4710
4767
  -execute[NUM] Execute multiple commands on one line
4768
+ -fileNUM ALTFILE Load tags from alternate file
4711
4769
  -list_dir List directories, not their contents
4712
4770
  -srcfile FMT Process a different source file
4713
4771
  -stay_open FLAG Keep reading -@ argfile even after EOF
@@ -4728,8 +4786,9 @@ L<Image::ExifTool::TagNames|Image::ExifTool::TagNames> for documentation on
4728
4786
  available tag names. A tag name may include leading group names separated
4729
4787
  by colons (eg. C<-EXIF:CreateDate>, or C<-Doc1:XMP:Creator>), and each group
4730
4788
  name may be prefixed by a digit to specify family number (eg.
4731
- C<-1IPTC:City>). Use the B<-listg> option to list available group names by
4732
- family.
4789
+ C<-1IPTC:City>). (Note that the API SavePath and SaveFormat options must be
4790
+ used for the family 5 and 6 groups respectively to be available.) Use the
4791
+ B<-listg> option to list available group names by family.
4733
4792
 
4734
4793
  A special tag name of C<All> may be used to indicate all meta information
4735
4794
  (ie. B<-All>). This is particularly useful when a group name is specified
@@ -4737,10 +4796,11 @@ to extract all information in a group (but beware that unless the B<-a>
4737
4796
  option is also used, some tags in the group may be suppressed by same-named
4738
4797
  tags in other groups). The wildcard characters C<?> and C<*> may be used in
4739
4798
  a tag name to match any single character and zero or more characters
4740
- respectively. These may not be used in a group name, with the exception that
4741
- a group name of C<*> (or C<All>) may be used to extract all instances of a
4742
- tag (as if B<-a> was used). Note that arguments containing wildcards must
4743
- be quoted on the command line of most systems to prevent shell globbing.
4799
+ respectively. These may not be used in a group name, with the exception
4800
+ that a group name of C<*> (or C<All>) may be used to extract all instances
4801
+ of a tag (as if B<-a> was used). Note that arguments containing wildcards
4802
+ must be quoted on the command line of most systems to prevent shell
4803
+ globbing.
4744
4804
 
4745
4805
  A C<#> may be appended to the tag name to disable the print conversion on a
4746
4806
  per-tag basis (see the B<-n> option). This may also be used when writing or
@@ -4819,6 +4879,9 @@ are removed if the containing group is deleted:
4819
4879
  - Deleting EXIF only removes ExifIFD which also deletes
4820
4880
  InteropIFD and MakerNotes.
4821
4881
 
4882
+ MOV/MP4 Video:
4883
+ - Deleting ItemList also deletes Keys tags.
4884
+
4822
4885
  Notes:
4823
4886
 
4824
4887
  1) B<Many tag values may be assigned in a single command>. If two
@@ -4915,7 +4978,9 @@ prevent shell redirection, and there is no C<=> sign as when assigning new
4915
4978
  values. Source and/or destination tags may be prefixed by a group name
4916
4979
  and/or suffixed by C<#>. Wildcards are allowed in both the source and
4917
4980
  destination tag names. A destination group and/or tag name of C<All> or
4918
- C<*> writes to the same family 1 group and/or tag name as the source. If no
4981
+ C<*> writes to the same family 1 group and/or tag name as the source (but
4982
+ the family may be specified by adding a leading number to the group name,
4983
+ eg. C<0All> writes to the same family 0 group as the source). If no
4919
4984
  destination group is specified, the information is written to the preferred
4920
4985
  group. Whitespace around the C<E<gt>> or C<E<lt>> is ignored. As a
4921
4986
  convenience, C<-tagsFromFile @> is assumed for any redirected tags which are
@@ -4973,16 +5038,14 @@ for list-type tags and conditional replacements because each copy operation
4973
5038
  on a tag overrides any previous operations. While this avoids duplicate
4974
5039
  list items when copying groups of tags from a file containing redundant
4975
5040
  information, it also prevents values of different tags from being copied
4976
- into the same list when this is the intent. So a B<-addTagsFromFile> option
4977
- is provided which allows copying of multiple tags into the same list. eg)
5041
+ into the same list when this is the intent. To accumulate values
5042
+ from different operations into the same list, add a C<+> after the initial
5043
+ C<-> of the argument. For example:
4978
5044
 
4979
- exiftool -addtagsfromfile @ '-subject<make' '-subject<model' ...
5045
+ exiftool -tagsfromfile @ '-subject<make' '-+subject<model' ...
4980
5046
 
4981
- Similarly, B<-addTagsFromFile> must be used when conditionally replacing a
4982
- tag to prevent overriding earlier conditions.
4983
-
4984
- Other than these differences, the B<-tagsFromFile> and B<-addTagsFromFile>
4985
- options are equivalent.
5047
+ Similarly, C<-+DSTTAG> must be used when conditionally replacing a tag to
5048
+ prevent overriding earlier conditions.
4986
5049
 
4987
5050
  6) The B<-a> option (allow duplicate tags) is always in effect when copying
4988
5051
  tags from I<SRCFILE>, but the highest priority tag is always copied last so
@@ -5249,12 +5312,12 @@ escaped. The inverse conversion is applied when writing tags.
5249
5312
 
5250
5313
  =item B<-f> (B<-forcePrint>)
5251
5314
 
5252
- Force printing of tags even if their values are not found. This option only
5253
- applies when specific tags are requested on the command line (ie. not with
5254
- wildcards or by C<-all>). With this option, a dash (C<->) is printed for
5255
- the value of any missing tag, but the dash may be changed via the API
5256
- MissingTagValue option. May also be used to add a 'flags' attribute to the
5257
- B<-listx> output, or to allow tags to be deleted when writing with the
5315
+ Force printing of tags even if they don't exist. This option applies to
5316
+ tags specified on the command line, or with the B<-p>, B<-if> or
5317
+ B<-tagsFromFile> options. When B<-f> is used, the value of any missing tag
5318
+ is set to a dash (C<->) by default, but this may be configured via the API
5319
+ MissingTagValue option. B<-f> is also used to add a 'flags' attribute to
5320
+ the B<-listx> output, or to allow tags to be deleted when writing with the
5258
5321
  B<-csv>=I<CSVFILE> feature.
5259
5322
 
5260
5323
  =item B<-g>[I<NUM>][:I<NUM>...] (B<-groupHeadings>)
@@ -5262,15 +5325,15 @@ B<-csv>=I<CSVFILE> feature.
5262
5325
  Organize output by tag group. I<NUM> specifies a group family number, and
5263
5326
  may be 0 (general location), 1 (specific location), 2 (category), 3
5264
5327
  (document number), 4 (instance number), 5 (metadata path), 6 (EXIF/TIFF
5265
- format) or 7 (tag ID). B<-g0> is assumed if a family number is not
5266
- specified. May be combined with other options to add group names to the
5267
- output. Multiple families may be specified by separating them with colons.
5268
- By default the resulting group name is simplified by removing any leading
5269
- C<Main:> and collapsing adjacent identical group names, but this can be
5270
- avoided by placing a colon before the first family number (eg. B<-g:3:1>).
5271
- Use the B<-listg> option to list group names for a specified family. The
5272
- API SavePath and SaveFormat options are automatically enabled if the
5273
- respective family 5 or 6 group names are requested. See the
5328
+ format), 7 (tag ID) or 8 (file number). B<-g0> is assumed if a family
5329
+ number is not specified. May be combined with other options to add group
5330
+ names to the output. Multiple families may be specified by separating them
5331
+ with colons. By default the resulting group name is simplified by removing
5332
+ any leading C<Main:> and collapsing adjacent identical group names, but this
5333
+ can be avoided by placing a colon before the first family number (eg.
5334
+ B<-g:3:1>). Use the B<-listg> option to list group names for a specified
5335
+ family. The API SavePath and SaveFormat options are automatically enabled
5336
+ if the respective family 5 or 6 group names are requested. See the
5274
5337
  L<API GetGroup documentation|Image::ExifTool/GetGroup> for more information.
5275
5338
 
5276
5339
  =item B<-G>[I<NUM>][:I<NUM>...] (B<-groupNames>)
@@ -5449,8 +5512,9 @@ which case the string is loaded from the contents of the file. Tag names in
5449
5512
  the format file or string begin with a C<$> symbol and may contain leading
5450
5513
  group names and/or a trailing C<#> (to disable print conversion). Case is
5451
5514
  not significant. Braces C<{}> may be used around the tag name to separate
5452
- it from subsequent text. Use C<$$> to represent a C<$> symbol, and C<$/>
5453
- for a newline.
5515
+ it from subsequent text (and must be used if subsequent text begins with an
5516
+ alphanumeric character, hyphen, underline, colon or number sign). Use C<$$>
5517
+ to represent a C<$> symbol, and C<$/> for a newline.
5454
5518
 
5455
5519
  Multiple B<-p> options may be used, each contributing a line (or more) of
5456
5520
  text to the output. Lines beginning with C<#[HEAD]> and C<#[TAIL]> are
@@ -5477,7 +5541,7 @@ with this command:
5477
5541
 
5478
5542
  produces output like this:
5479
5543
 
5480
- -- Generated by ExifTool 12.56 --
5544
+ -- Generated by ExifTool 12.60 --
5481
5545
  File: a.jpg - 2003:10:31 15:44:19
5482
5546
  (f/5.6, 1/60s, ISO 100)
5483
5547
  File: b.jpg - 2006:05:23 11:57:38
@@ -6110,7 +6174,7 @@ If a password is required but not given, a warning is issued and the
6110
6174
  document is not processed. This option is ignored if a password is not
6111
6175
  required.
6112
6176
 
6113
- =item B<-progress>[:[I<TITLE>]]
6177
+ =item B<-progress>[NUM][:[I<TITLE>]]
6114
6178
 
6115
6179
  Show the progress when processing files. Without a colon, the B<-progress>
6116
6180
  option adds a progress count in brackets after the name of each processed
@@ -6118,17 +6182,19 @@ file, giving the current file number and the total number of files to be
6118
6182
  processed. Implies the B<-v0> option, causing the names of processed files
6119
6183
  to also be printed when writing. When combined with the B<-if> option, the
6120
6184
  total count includes all files before the condition is applied, but files
6121
- that fail the condition will not have their names printed.
6185
+ that fail the condition will not have their names printed. If NUM is
6186
+ specified, the progress is shown every NUM input files.
6122
6187
 
6123
6188
  If followed by a colon (ie. B<-progress:>), the console window title is set
6124
6189
  according to the specified I<TITLE> string. If no I<TITLE> is given, a
6125
6190
  default I<TITLE> string of "ExifTool %p%%" is assumed. In the string, %f
6126
6191
  represents the file name, %p is the progress as a percent, %r is the
6127
- progress as a ratio, %##b is a progress bar of width "##" (20 characters if
6128
- "##" is omitted), and %% is a % character. May be combined with the normal
6129
- B<-progress> option to also show the progress count in console messages.
6130
- (Note: For this feature to function correctly on Mac/Linux, stderr must go
6131
- to the console.)
6192
+ progress as a ratio, %##b is a progress bar of width "##" (where "##" is an
6193
+ integer specifying the bar width in characters, or 20 characters by default
6194
+ if "##" is omitted), and %% is a % character. May be combined with the
6195
+ normal B<-progress> option to also show the progress count in console
6196
+ messages. (Note: For this feature to function correctly on Mac/Linux, stderr
6197
+ must go to the console.)
6132
6198
 
6133
6199
  =item B<-q> (B<-quiet>)
6134
6200
 
@@ -6366,12 +6432,12 @@ I<SHIFT> string. For example:
6366
6432
 
6367
6433
  Add features from specified plug-in I<MODULE>. Currently, the MWG module is
6368
6434
  the only plug-in module distributed with exiftool. This module adds
6369
- read/write support for tags as recommended by the Metadata Working Group.
6370
- As a convenience, C<-use MWG> is assumed if the C<MWG> group is specified
6371
- for any tag on the command line. See the L<MWG Tags
6372
- documentation|Image::ExifTool::TagNames/MWG Tags> for more details. Note
6373
- that this option is not reversible, and remains in effect until the
6374
- application terminates, even across the B<-execute> option.
6435
+ read/write support for tags as recommended by the Metadata Working Group. As
6436
+ a convenience, C<-use MWG> is assumed if the group name prefix starts with
6437
+ C<MWG:> exactly for any requested tag. See the
6438
+ L<MWG Tags documentation|Image::ExifTool::TagNames/MWG Tags> for more
6439
+ details. Note that this option is not reversible, and remains in effect
6440
+ until the application terminates, even across the B<-execute> option.
6375
6441
 
6376
6442
  =back
6377
6443
 
@@ -6457,10 +6523,11 @@ exit status of the command (see L</EXIT STATUS>).
6457
6523
 
6458
6524
  Save the names of files giving errors (I<NUM> missing or 1), files that were
6459
6525
  unchanged (I<NUM> is 2), files that fail the B<-if> condition (I<NUM> is 4),
6460
- or any combination thereof by summing I<NUM> (eg. B<-efile3> is the same
6461
- has having both B<-efile> and B<-efile2> options with the same I<ERRFILE>).
6462
- By default, file names are appended to any existing I<ERRFILE>, but
6463
- I<ERRFILE> is overwritten if an exclamation point is added to the option
6526
+ files that were updated (I<NUM> is 8), files that were created (I<NUM> is
6527
+ 16), or any combination thereof by summing I<NUM> (eg. B<-efile3> is the
6528
+ same has having both B<-efile> and B<-efile2> options with the same
6529
+ I<ERRFILE>). By default, file names are appended to any existing I<ERRFILE>,
6530
+ but I<ERRFILE> is overwritten if an exclamation point is added to the option
6464
6531
  (eg. B<-efile!>). Saves the name of the file specified by the B<-srcfile>
6465
6532
  option if applicable.
6466
6533
 
@@ -6475,6 +6542,14 @@ line. I<NUM> is an optional number that is echoed in the "{ready}" message
6475
6542
  when using the B<-stay_open> feature. If a I<NUM> is specified, the B<-q>
6476
6543
  option no longer suppresses the output "{readyNUM}" message.
6477
6544
 
6545
+ =item B<-file>I<NUM> I<ALTFILE>
6546
+
6547
+ Read tags from an alternate source file. These tags are accessed via the
6548
+ family 8 group name (eg. C<File1:TAG> for the B<-file1> option, C<File2:TAG>
6549
+ for B<-file2>, etc). I<ALTFILE> may contain filename formatting codes %d,
6550
+ %f and %e. Among other things, this allows tags from different files to be
6551
+ compared and combined using the B<-if> and B<-p> options.
6552
+
6478
6553
  =item B<-list_dir>
6479
6554
 
6480
6555
  List directories themselves instead of their contents. This option