exiftool_vendored 10.65.0 → 11.41.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of exiftool_vendored might be problematic. Click here for more details.

Files changed (205) hide show
  1. checksums.yaml +4 -4
  2. data/bin/Changes +818 -19
  3. data/bin/MANIFEST +38 -0
  4. data/bin/META.json +1 -1
  5. data/bin/META.yml +1 -1
  6. data/bin/README +48 -44
  7. data/bin/arg_files/exif2xmp.args +4 -1
  8. data/bin/arg_files/gps2xmp.args +4 -1
  9. data/bin/arg_files/iptcCore.args +8 -0
  10. data/bin/arg_files/xmp2exif.args +4 -1
  11. data/bin/arg_files/xmp2gps.args +4 -1
  12. data/bin/config_files/dji.config +131 -0
  13. data/bin/config_files/example.config +6 -2
  14. data/bin/config_files/gps2utm.config +256 -256
  15. data/bin/config_files/nksc.config +146 -0
  16. data/bin/config_files/picasa_faces.config +382 -382
  17. data/bin/exiftool +688 -408
  18. data/bin/fmt_files/gpx.fmt +10 -6
  19. data/bin/fmt_files/gpx_wpt.fmt +10 -6
  20. data/bin/fmt_files/kml.fmt +8 -5
  21. data/bin/lib/File/RandomAccess.pm +48 -8
  22. data/bin/lib/File/RandomAccess.pod +21 -2
  23. data/bin/lib/Image/ExifTool.pm +645 -256
  24. data/bin/lib/Image/ExifTool.pod +219 -164
  25. data/bin/lib/Image/ExifTool/AES.pm +1 -1
  26. data/bin/lib/Image/ExifTool/AFCP.pm +3 -8
  27. data/bin/lib/Image/ExifTool/AIFF.pm +12 -4
  28. data/bin/lib/Image/ExifTool/APE.pm +1 -1
  29. data/bin/lib/Image/ExifTool/APP12.pm +1 -1
  30. data/bin/lib/Image/ExifTool/ASF.pm +19 -6
  31. data/bin/lib/Image/ExifTool/Apple.pm +13 -5
  32. data/bin/lib/Image/ExifTool/Audible.pm +1 -1
  33. data/bin/lib/Image/ExifTool/BMP.pm +1 -1
  34. data/bin/lib/Image/ExifTool/BPG.pm +17 -15
  35. data/bin/lib/Image/ExifTool/BZZ.pm +1 -1
  36. data/bin/lib/Image/ExifTool/BigTIFF.pm +30 -15
  37. data/bin/lib/Image/ExifTool/BuildTagLookup.pm +103 -52
  38. data/bin/lib/Image/ExifTool/Canon.pm +684 -112
  39. data/bin/lib/Image/ExifTool/CanonCustom.pm +119 -9
  40. data/bin/lib/Image/ExifTool/CanonRaw.pm +1 -1
  41. data/bin/lib/Image/ExifTool/CanonVRD.pm +13 -26
  42. data/bin/lib/Image/ExifTool/CaptureOne.pm +1 -1
  43. data/bin/lib/Image/ExifTool/Casio.pm +1 -1
  44. data/bin/lib/Image/ExifTool/Charset.pm +1 -1
  45. data/bin/lib/Image/ExifTool/DICOM.pm +12 -5
  46. data/bin/lib/Image/ExifTool/DJI.pm +51 -3
  47. data/bin/lib/Image/ExifTool/DNG.pm +15 -8
  48. data/bin/lib/Image/ExifTool/DPX.pm +1 -1
  49. data/bin/lib/Image/ExifTool/DV.pm +1 -1
  50. data/bin/lib/Image/ExifTool/DarwinCore.pm +63 -23
  51. data/bin/lib/Image/ExifTool/DjVu.pm +4 -2
  52. data/bin/lib/Image/ExifTool/EXE.pm +30 -6
  53. data/bin/lib/Image/ExifTool/Exif.pm +351 -109
  54. data/bin/lib/Image/ExifTool/FITS.pm +148 -0
  55. data/bin/lib/Image/ExifTool/FLAC.pm +2 -2
  56. data/bin/lib/Image/ExifTool/FLIF.pm +1 -1
  57. data/bin/lib/Image/ExifTool/FLIR.pm +109 -13
  58. data/bin/lib/Image/ExifTool/Fixup.pm +1 -1
  59. data/bin/lib/Image/ExifTool/Flash.pm +3 -3
  60. data/bin/lib/Image/ExifTool/FlashPix.pm +433 -9
  61. data/bin/lib/Image/ExifTool/Font.pm +2 -2
  62. data/bin/lib/Image/ExifTool/FotoStation.pm +1 -1
  63. data/bin/lib/Image/ExifTool/FujiFilm.pm +336 -16
  64. data/bin/lib/Image/ExifTool/GE.pm +1 -1
  65. data/bin/lib/Image/ExifTool/GIF.pm +5 -7
  66. data/bin/lib/Image/ExifTool/GIMP.pm +39 -3
  67. data/bin/lib/Image/ExifTool/GPS.pm +48 -22
  68. data/bin/lib/Image/ExifTool/GeoTiff.pm +23 -23
  69. data/bin/lib/Image/ExifTool/Geotag.pm +80 -45
  70. data/bin/lib/Image/ExifTool/GoPro.pm +709 -0
  71. data/bin/lib/Image/ExifTool/H264.pm +40 -18
  72. data/bin/lib/Image/ExifTool/HP.pm +1 -1
  73. data/bin/lib/Image/ExifTool/HTML.pm +19 -12
  74. data/bin/lib/Image/ExifTool/HtmlDump.pm +37 -26
  75. data/bin/lib/Image/ExifTool/ICC_Profile.pm +297 -23
  76. data/bin/lib/Image/ExifTool/ID3.pm +12 -7
  77. data/bin/lib/Image/ExifTool/IPTC.pm +48 -19
  78. data/bin/lib/Image/ExifTool/ISO.pm +1 -1
  79. data/bin/lib/Image/ExifTool/ITC.pm +1 -1
  80. data/bin/lib/Image/ExifTool/Import.pm +13 -9
  81. data/bin/lib/Image/ExifTool/InDesign.pm +3 -5
  82. data/bin/lib/Image/ExifTool/JPEG.pm +22 -11
  83. data/bin/lib/Image/ExifTool/JPEGDigest.pm +1 -1
  84. data/bin/lib/Image/ExifTool/JSON.pm +3 -3
  85. data/bin/lib/Image/ExifTool/JVC.pm +1 -1
  86. data/bin/lib/Image/ExifTool/Jpeg2000.pm +2 -2
  87. data/bin/lib/Image/ExifTool/Kodak.pm +1233 -58
  88. data/bin/lib/Image/ExifTool/KyoceraRaw.pm +1 -1
  89. data/bin/lib/Image/ExifTool/LNK.pm +1 -1
  90. data/bin/lib/Image/ExifTool/Lang/cs.pm +1 -1
  91. data/bin/lib/Image/ExifTool/Lang/de.pm +33 -24
  92. data/bin/lib/Image/ExifTool/Lang/en_ca.pm +64 -2
  93. data/bin/lib/Image/ExifTool/Lang/en_gb.pm +64 -2
  94. data/bin/lib/Image/ExifTool/Lang/es.pm +8 -4
  95. data/bin/lib/Image/ExifTool/Lang/fi.pm +46 -4
  96. data/bin/lib/Image/ExifTool/Lang/fr.pm +5 -3
  97. data/bin/lib/Image/ExifTool/Lang/it.pm +6 -3
  98. data/bin/lib/Image/ExifTool/Lang/ja.pm +15 -3
  99. data/bin/lib/Image/ExifTool/Lang/ko.pm +5 -2
  100. data/bin/lib/Image/ExifTool/Lang/nl.pm +6 -3
  101. data/bin/lib/Image/ExifTool/Lang/pl.pm +2 -2
  102. data/bin/lib/Image/ExifTool/Lang/ru.pm +1 -1
  103. data/bin/lib/Image/ExifTool/Lang/sv.pm +1 -1
  104. data/bin/lib/Image/ExifTool/Lang/tr.pm +4 -2
  105. data/bin/lib/Image/ExifTool/Lang/zh_cn.pm +1 -1
  106. data/bin/lib/Image/ExifTool/Lang/zh_tw.pm +1 -1
  107. data/bin/lib/Image/ExifTool/Leaf.pm +1 -1
  108. data/bin/lib/Image/ExifTool/Lytro.pm +4 -8
  109. data/bin/lib/Image/ExifTool/M2TS.pm +10 -9
  110. data/bin/lib/Image/ExifTool/MIE.pm +12 -8
  111. data/bin/lib/Image/ExifTool/MIEUnits.pod +1 -1
  112. data/bin/lib/Image/ExifTool/MIFF.pm +1 -1
  113. data/bin/lib/Image/ExifTool/MNG.pm +1 -1
  114. data/bin/lib/Image/ExifTool/MOI.pm +1 -1
  115. data/bin/lib/Image/ExifTool/MPC.pm +1 -1
  116. data/bin/lib/Image/ExifTool/MPEG.pm +2 -3
  117. data/bin/lib/Image/ExifTool/MPF.pm +6 -6
  118. data/bin/lib/Image/ExifTool/MWG.pm +4 -4
  119. data/bin/lib/Image/ExifTool/MXF.pm +2 -2
  120. data/bin/lib/Image/ExifTool/MacOS.pm +184 -34
  121. data/bin/lib/Image/ExifTool/MakerNotes.pm +101 -18
  122. data/bin/lib/Image/ExifTool/Matroska.pm +1 -1
  123. data/bin/lib/Image/ExifTool/Microsoft.pm +5 -3
  124. data/bin/lib/Image/ExifTool/Minolta.pm +89 -62
  125. data/bin/lib/Image/ExifTool/MinoltaRaw.pm +1 -1
  126. data/bin/lib/Image/ExifTool/Motorola.pm +1 -1
  127. data/bin/lib/Image/ExifTool/Nikon.pm +1511 -380
  128. data/bin/lib/Image/ExifTool/NikonCapture.pm +1 -1
  129. data/bin/lib/Image/ExifTool/NikonCustom.pm +2758 -2935
  130. data/bin/lib/Image/ExifTool/Nintendo.pm +1 -1
  131. data/bin/lib/Image/ExifTool/OOXML.pm +1 -1
  132. data/bin/lib/Image/ExifTool/Ogg.pm +1 -1
  133. data/bin/lib/Image/ExifTool/Olympus.pm +47 -8
  134. data/bin/lib/Image/ExifTool/OpenEXR.pm +1 -1
  135. data/bin/lib/Image/ExifTool/Opus.pm +1 -1
  136. data/bin/lib/Image/ExifTool/PCX.pm +138 -0
  137. data/bin/lib/Image/ExifTool/PDF.pm +58 -42
  138. data/bin/lib/Image/ExifTool/PGF.pm +1 -1
  139. data/bin/lib/Image/ExifTool/PICT.pm +1 -1
  140. data/bin/lib/Image/ExifTool/PLIST.pm +12 -5
  141. data/bin/lib/Image/ExifTool/PLUS.pm +1 -1
  142. data/bin/lib/Image/ExifTool/PNG.pm +108 -10
  143. data/bin/lib/Image/ExifTool/PPM.pm +3 -3
  144. data/bin/lib/Image/ExifTool/PSP.pm +1 -1
  145. data/bin/lib/Image/ExifTool/Palm.pm +1 -1
  146. data/bin/lib/Image/ExifTool/Panasonic.pm +299 -31
  147. data/bin/lib/Image/ExifTool/PanasonicRaw.pm +201 -19
  148. data/bin/lib/Image/ExifTool/Pentax.pm +164 -143
  149. data/bin/lib/Image/ExifTool/PhaseOne.pm +12 -5
  150. data/bin/lib/Image/ExifTool/PhotoCD.pm +9 -10
  151. data/bin/lib/Image/ExifTool/PhotoMechanic.pm +1 -1
  152. data/bin/lib/Image/ExifTool/Photoshop.pm +230 -60
  153. data/bin/lib/Image/ExifTool/PostScript.pm +29 -4
  154. data/bin/lib/Image/ExifTool/PrintIM.pm +1 -1
  155. data/bin/lib/Image/ExifTool/Qualcomm.pm +2 -2
  156. data/bin/lib/Image/ExifTool/QuickTime.pm +1539 -279
  157. data/bin/lib/Image/ExifTool/QuickTimeStream.pl +1857 -0
  158. data/bin/lib/Image/ExifTool/README +84 -46
  159. data/bin/lib/Image/ExifTool/RIFF.pm +116 -23
  160. data/bin/lib/Image/ExifTool/RSRC.pm +1 -1
  161. data/bin/lib/Image/ExifTool/RTF.pm +6 -4
  162. data/bin/lib/Image/ExifTool/Radiance.pm +1 -1
  163. data/bin/lib/Image/ExifTool/Rawzor.pm +3 -2
  164. data/bin/lib/Image/ExifTool/Real.pm +1 -1
  165. data/bin/lib/Image/ExifTool/Reconyx.pm +261 -7
  166. data/bin/lib/Image/ExifTool/Red.pm +325 -0
  167. data/bin/lib/Image/ExifTool/Ricoh.pm +3 -7
  168. data/bin/lib/Image/ExifTool/Samsung.pm +95 -25
  169. data/bin/lib/Image/ExifTool/Sanyo.pm +1 -1
  170. data/bin/lib/Image/ExifTool/Scalado.pm +1 -1
  171. data/bin/lib/Image/ExifTool/Shift.pl +26 -12
  172. data/bin/lib/Image/ExifTool/Shortcuts.pm +9 -2
  173. data/bin/lib/Image/ExifTool/Sigma.pm +36 -30
  174. data/bin/lib/Image/ExifTool/SigmaRaw.pm +3 -8
  175. data/bin/lib/Image/ExifTool/Sony.pm +531 -177
  176. data/bin/lib/Image/ExifTool/SonyIDC.pm +63 -3
  177. data/bin/lib/Image/ExifTool/Stim.pm +2 -2
  178. data/bin/lib/Image/ExifTool/TagInfoXML.pm +23 -23
  179. data/bin/lib/Image/ExifTool/TagLookup.pm +6352 -5062
  180. data/bin/lib/Image/ExifTool/TagNames.pod +3024 -565
  181. data/bin/lib/Image/ExifTool/Theora.pm +1 -1
  182. data/bin/lib/Image/ExifTool/Torrent.pm +2 -2
  183. data/bin/lib/Image/ExifTool/Unknown.pm +1 -1
  184. data/bin/lib/Image/ExifTool/VCard.pm +47 -9
  185. data/bin/lib/Image/ExifTool/Validate.pm +391 -99
  186. data/bin/lib/Image/ExifTool/Vorbis.pm +1 -1
  187. data/bin/lib/Image/ExifTool/WTV.pm +319 -0
  188. data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
  189. data/bin/lib/Image/ExifTool/WriteExif.pl +91 -18
  190. data/bin/lib/Image/ExifTool/WriteIPTC.pl +6 -6
  191. data/bin/lib/Image/ExifTool/WritePDF.pl +13 -12
  192. data/bin/lib/Image/ExifTool/WritePNG.pl +1 -1
  193. data/bin/lib/Image/ExifTool/WritePhotoshop.pl +1 -1
  194. data/bin/lib/Image/ExifTool/WritePostScript.pl +2 -2
  195. data/bin/lib/Image/ExifTool/WriteQuickTime.pl +764 -121
  196. data/bin/lib/Image/ExifTool/WriteXMP.pl +176 -67
  197. data/bin/lib/Image/ExifTool/Writer.pl +490 -246
  198. data/bin/lib/Image/ExifTool/XMP.pm +216 -76
  199. data/bin/lib/Image/ExifTool/XMP2.pl +54 -10
  200. data/bin/lib/Image/ExifTool/XMPStruct.pl +14 -11
  201. data/bin/lib/Image/ExifTool/ZIP.pm +60 -15
  202. data/bin/lib/Image/ExifTool/iWork.pm +12 -5
  203. data/bin/perl-Image-ExifTool.spec +46 -44
  204. data/lib/exiftool_vendored/version.rb +1 -1
  205. metadata +14 -4
data/bin/exiftool CHANGED
@@ -12,13 +12,20 @@
12
12
  use strict;
13
13
  require 5.004;
14
14
 
15
- my $version = '10.65';
15
+ my $version = '11.41';
16
16
 
17
17
  # add our 'lib' directory to the include list BEFORE 'use Image::ExifTool'
18
18
  my $exeDir;
19
19
  BEGIN {
20
20
  # get exe directory
21
21
  $exeDir = ($0 =~ /(.*)[\\\/]/) ? $1 : '.';
22
+ if (-l $0) {
23
+ my $lnk = eval { readlink $0 };
24
+ if (defined $lnk) {
25
+ my $lnkDir = ($lnk =~ /(.*)[\\\/]/) ? $1 : '.';
26
+ $exeDir = (($lnk =~ m(^/)) ? '' : $exeDir . '/') . $lnkDir;
27
+ }
28
+ }
22
29
  # add lib directory at start of include path
23
30
  unshift @INC, "$exeDir/lib";
24
31
  # load or disable config file if specified
@@ -35,7 +42,7 @@ sub SigCont();
35
42
  sub Cleanup();
36
43
  sub GetImageInfo($$);
37
44
  sub SetImageInfo($$$);
38
- sub DoHardLink($$$$);
45
+ sub DoHardLink($$$$$);
39
46
  sub CleanXML($);
40
47
  sub EncodeXML($);
41
48
  sub FormatXML($$$);
@@ -65,6 +72,7 @@ sub CreateDirectory($);
65
72
  sub OpenOutputFile($;@);
66
73
  sub AcceptFile($);
67
74
  sub SlurpFile($$);
75
+ sub FilterArgfileLine($);
68
76
  sub ReadStayOpen($);
69
77
  sub PrintTagList($@);
70
78
  sub PrintErrors($$$);
@@ -77,6 +85,7 @@ END {
77
85
 
78
86
  # declare all static file-scope variables
79
87
  my @commonArgs; # arguments common to all commands
88
+ my @condition; # conditional processing of files
80
89
  my @csvFiles; # list of files when reading with CSV option (in ExifTool Charset)
81
90
  my @csvTags; # order of tags for first file with CSV option (lower case)
82
91
  my @delFiles; # list of files to delete
@@ -90,6 +99,7 @@ my @requestTags; # tags to request (for -p or -if option arguments)
90
99
  my @srcFmt; # source file name format strings
91
100
  my @tags; # list of tags to extract
92
101
  my %appended; # list of files appended to
102
+ my %countLink; # count hard and symbolic links made
93
103
  my %created; # list of files we created
94
104
  my %csvTags; # lookup for all found tags with CSV option (lower case keys)
95
105
  my %database; # lookup for database information based on file name (in ExifTool Charset)
@@ -104,22 +114,22 @@ my %utf8FileName; # lookup for file names that are UTF-8 encoded
104
114
  my %warnedOnce; # lookup for once-only warnings
105
115
  my %wext; # -W extensions to write
106
116
  my $allGroup; # show group name for all tags
117
+ my $altEnc; # alternate character encoding if not UTF-8
107
118
  my $argFormat; # use exiftool argument-format output
108
119
  my $binaryOutput; # flag for binary output (undef or 1, or 0 for binary XML/PHP)
109
120
  my $binaryStdout; # flag set if we output binary to stdout
121
+ my $binSep; # separator used for list items in binary output
122
+ my $binTerm; # terminator used for binary output
110
123
  my $comma; # flag set if we need a comma in JSON output
111
- my $condition; # conditional processing of files
112
- my $count; # count of files scanned
124
+ my $count; # count of files scanned when reading or deleting originals
113
125
  my $countBad; # count of files with errors
114
126
  my $countBadCr; # count files not created due to errors
115
- my $countBadLink; # count bad links
116
127
  my $countBadWr; # count write errors
117
128
  my $countCopyWr; # count of files copied without being changed
118
129
  my $countDir; # count of directories scanned
119
130
  my $countFailed; # count files that failed condition
120
131
  my $countGoodCr; # count files created OK
121
132
  my $countGoodWr; # count files written OK
122
- my $countLink; # count number of links created
123
133
  my $countNewDir; # count of directories created
124
134
  my $countSameWr; # count files written OK but not changed
125
135
  my $critical; # flag for critical operations (disable CTRL-C)
@@ -133,6 +143,8 @@ my $doUnzip; # flag to extract info from .gz and .bz2 files
133
143
  my $escapeHTML; # flag to escape printed values for html
134
144
  my $evalWarning; # warning from eval
135
145
  my $executeID; # -execute ID number
146
+ my $failCondition; # flag to fail -if condition
147
+ my $fastCondition; # flag for fast -if condition
136
148
  my $fileHeader; # header to print to output file (or console, once)
137
149
  my $fileTrailer; # trailer for output file
138
150
  my $filtered; # flag indicating file was filtered by name
@@ -163,11 +175,14 @@ my $quiet; # flag to disable printing of informational messages / warni
163
175
  my $rafStdin; # File::RandomAccess for stdin (if necessary to rewind)
164
176
  my $recurse; # recurse into subdirectories (2=also hidden directories)
165
177
  my $rtnVal; # command return value (0=success)
178
+ my $rtnValPrev; # previous command return value (0=success)
166
179
  my $saveCount; # count the number of times we will/did call SaveNewValues()
167
180
  my $scanWritable; # flag to process only writable file types
168
181
  my $sectHeader; # current section header for -p option
169
182
  my $sectTrailer; # section trailer for -p option
183
+ my $seqFileBase; # sequential file number at start of directory
170
184
  my $seqFileNum; # sequential file number used for %C
185
+ my $setCharset; # character set setting ('default' if not set and -csv -b used)
171
186
  my $showGroup; # number of group to show (may be zero or '')
172
187
  my $showTagID; # non-zero to show tag ID's
173
188
  my $stayOpenBuff='';# buffer for -stay_open file
@@ -179,7 +194,6 @@ my $textOut; # extension for text output file (or undef for no output)
179
194
  my $textOverwrite; # flag to overwrite existing text output file (2=append, 3=over+append)
180
195
  my $tmpFile; # temporary file to delete on exit
181
196
  my $tmpText; # temporary text file
182
- my $utf8; # flag set if we are using UTF-8 encoding
183
197
  my $validFile; # flag indicating we processed a valid file
184
198
  my $verbose; # verbose setting
185
199
  my $vout; # verbose output file reference (\*STDOUT or \*STDERR)
@@ -193,6 +207,7 @@ my $xml; # flag for XML-formatted output
193
207
  # 3 = waiting for -@ to switch to a new STAYOPEN argfile
194
208
  my $stayOpen = 0;
195
209
 
210
+ my $rtnValApp = 0; # app return value (0=success)
196
211
  my $curTitle = ''; # current window title
197
212
 
198
213
  # lookup for O/S names which may use a backslash as a directory separator
@@ -224,7 +239,7 @@ my %optArgs = (
224
239
  '-geotag' => 1,
225
240
  '-globaltimeshift' => 1,
226
241
  '-i' => 1, '-ignore' => 1,
227
- '-if' => 1,
242
+ '-if' => 1, '-if0' => 1, '-if1' => 1, '-if2' => 1, '-if3' => 1, '-if4' => 1,
228
243
  '-lang' => 0, # (optional arg; cannot begin with "-")
229
244
  '-listitem' => 1,
230
245
  '-o' => 1, '-out' => 1,
@@ -241,7 +256,7 @@ my %optArgs = (
241
256
  '-textout' => 1, '-textout!' => 1, '-textout+' => 1, '-textout+!' => 1, '-textout!+' => 1,
242
257
  '-tagout' => 1, '-tagout!' => 1, '-tagout+' => 1, '-tagout+!' => 1, '-tagout!+' => 1,
243
258
  '-wext' => 1,
244
- '-wm' => 1,
259
+ '-wm' => 1, '-writemode' => 1,
245
260
  '-x' => 1, '-exclude' => 1,
246
261
  '-X' => 0,
247
262
  );
@@ -265,6 +280,8 @@ my %altRecommends = (
265
280
  'POSIX::strptime' => 'Time::Piece', # (can use Time::Piece instead of POSIX::strptime)
266
281
  );
267
282
 
283
+ my %unescapeChar = ( 't'=>"\t", 'n'=>"\n", 'r'=>"\r" );
284
+
268
285
  # exit routine
269
286
  sub Exit {
270
287
  if ($pause) {
@@ -340,6 +357,10 @@ Command: for (;;) {
340
357
  $rafStdin->Close() if $rafStdin;
341
358
  undef $rafStdin;
342
359
 
360
+ # save or previous return codes
361
+ $rtnValPrev = $rtnVal;
362
+ $rtnValApp = $rtnVal if $rtnVal;
363
+
343
364
  # exit Command loop now if we are all done processing commands
344
365
  last unless @ARGV or not defined $rtnVal or $stayOpen >= 2 or @commonArgs;
345
366
 
@@ -364,11 +385,10 @@ if ($stayOpen >= 2) {
364
385
  }
365
386
  }
366
387
 
367
- $rtnVal = 0 unless defined $rtnVal;
368
-
369
388
  # initialize necessary static file-scope variables
370
389
  # (not done: @commonArgs, @moreArgs, $critical, $binaryStdout, $helped,
371
- # $interrupted, $mt, $pause, $rtnVal, $stayOpen, $stayOpenBuff, $stayOpenFile)
390
+ # $interrupted, $mt, $pause, $rtnValApp, $rtnValPrev, $stayOpen, $stayOpenBuff, $stayOpenFile)
391
+ undef @condition;
372
392
  undef @csvFiles;
373
393
  undef @csvTags;
374
394
  undef @delFiles;
@@ -381,6 +401,7 @@ undef @newValues;
381
401
  undef @srcFmt;
382
402
  undef @tags;
383
403
  undef %appended;
404
+ undef %countLink;
384
405
  undef %created;
385
406
  undef %csvTags;
386
407
  undef %database;
@@ -395,10 +416,12 @@ undef %utf8FileName;
395
416
  undef %warnedOnce;
396
417
  undef %wext;
397
418
  undef $allGroup;
419
+ undef $altEnc;
398
420
  undef $argFormat;
399
421
  undef $binaryOutput;
422
+ undef $binSep;
423
+ undef $binTerm;
400
424
  undef $comma;
401
- undef $condition;
402
425
  undef $csv;
403
426
  undef $csvAdd;
404
427
  undef $deleteOrig;
@@ -408,6 +431,8 @@ undef $doUnzip;
408
431
  undef $escapeHTML;
409
432
  undef $evalWarning;
410
433
  undef $executeID;
434
+ undef $failCondition;
435
+ undef $fastCondition;
411
436
  undef $fileHeader;
412
437
  undef $filtered;
413
438
  undef $fixLen;
@@ -424,6 +449,7 @@ undef $progressMax;
424
449
  undef $recurse;
425
450
  undef $scanWritable;
426
451
  undef $sectHeader;
452
+ undef $setCharset;
427
453
  undef $showGroup;
428
454
  undef $showTagID;
429
455
  undef $structOpt;
@@ -439,14 +465,12 @@ undef $windowTitle;
439
465
  $count = 0;
440
466
  $countBad = 0;
441
467
  $countBadCr = 0;
442
- $countBadLink = 0;
443
468
  $countBadWr = 0;
444
469
  $countCopyWr = 0;
445
470
  $countDir = 0;
446
471
  $countFailed = 0;
447
472
  $countGoodCr = 0;
448
473
  $countGoodWr = 0;
449
- $countLink = 0;
450
474
  $countNewDir = 0;
451
475
  $countSameWr = 0;
452
476
  $csvSaveCount = 0;
@@ -460,11 +484,12 @@ $outFormat = 0;
460
484
  $overwriteOrig = 0;
461
485
  $progStr = '';
462
486
  $quiet = 0;
487
+ $rtnVal = 0;
463
488
  $saveCount = 0;
464
489
  $sectTrailer = '';
490
+ $seqFileBase = 0;
465
491
  $seqFileNum = 0;
466
492
  $tabFormat = 0;
467
- $utf8 = 1;
468
493
  $vout = \*STDOUT;
469
494
  $xml = 0;
470
495
 
@@ -510,15 +535,17 @@ if (not $preserveTime and $^O eq 'MSWin32') {
510
535
  for (;;) {
511
536
 
512
537
  # execute the command now if no more arguments or -execute is used
513
- if (not @ARGV or $ARGV[0] =~ /^-execute(\d*)$/i) {
538
+ if (not @ARGV or $ARGV[0] =~ /^(-|\xe2\x88\x92)execute(\d*)$/i) {
514
539
  if (@ARGV) {
515
- $executeID = $1; # save -execute number for "{ready}" response
540
+ $executeID = $2; # save -execute number for "{ready}" response
516
541
  $helped = 1; # don't show help if we used -execute
517
- $badCmd and shift, next Command;
542
+ $badCmd and shift, $rtnVal=1, next Command;
518
543
  } elsif ($stayOpen >= 2) {
519
544
  ReadStayOpen(\@ARGV); # read more arguments from -stay_open file
520
545
  next;
521
546
  } elsif ($badCmd) {
547
+ undef @commonArgs; # all done. Flush common arguments
548
+ $rtnVal = 1;
522
549
  next Command;
523
550
  }
524
551
  if ($pass == 0) {
@@ -547,6 +574,13 @@ for (;;) {
547
574
  require Image::ExifTool::MWG;
548
575
  Image::ExifTool::MWG::Load();
549
576
  }
577
+ # update necessary variables for 2nd pass
578
+ if (defined $forcePrint) {
579
+ unless (defined $mt->Options('MissingTagValue')) {
580
+ $mt->Options(MissingTagValue => '-');
581
+ }
582
+ $forcePrint = $mt->Options('MissingTagValue');
583
+ }
550
584
  }
551
585
  if (@nextPass) {
552
586
  # process arguments which were deferred to the next pass
@@ -699,11 +733,8 @@ for (;;) {
699
733
  s/^\xef\xbb\xbf//;
700
734
  $didBOM = 1;
701
735
  }
702
- next if /^#/; # ignore lines beginning with '#'
703
- s/^\s+//; s/[\x0d\x0a]+$//s; # remove leading white space and trailing newline
704
- # remove white space before, and single space after '=', '+=', '-=' or '<='
705
- s/^(-[-:\w]+#?)\s*([-+<]?=) ?/$1$2/;
706
- push @newArgs, $_ unless $_ eq '';
736
+ $_ = FilterArgfileLine($_);
737
+ push @newArgs, $_ if defined $_;
707
738
  }
708
739
  close ARGFILE;
709
740
  unshift @ARGV, @newArgs;
@@ -714,9 +745,9 @@ for (;;) {
714
745
  my $opt = shift;
715
746
  defined $opt or Error("Expected OPT[=VAL] argument for -api option\n"), $badCmd=1, next;
716
747
  my $val = ($opt =~ s/=(.*)//s) ? $1 : 1;
717
- $mt->Options($opt => (length($val) ? $val : undef));
718
- # update $forcePrint in case MissingTagValue was changed
719
- $forcePrint = $mt->Options('MissingTagValue') if defined $forcePrint;
748
+ # empty string means an undefined value unless ^= is used
749
+ $val = undef unless $opt =~ s/\^$// or length $val;
750
+ $mt->Options($opt => $val);
720
751
  next;
721
752
  }
722
753
  /^arg(s|format)$/i and $argFormat = 1, next;
@@ -736,8 +767,16 @@ for (;;) {
736
767
  PrintTagList('Available character sets', sort keys %charsets);
737
768
  $helped = 1;
738
769
  } elsif ($charset !~ s/^(\w+)=// or lc($1) eq 'exiftool') {
739
- $mt->Options(Charset => $charset);
740
- $utf8 = ($mt->Options('Charset') eq 'UTF8');
770
+ {
771
+ local $SIG{'__WARN__'} = sub { $evalWarning = $_[0] };
772
+ undef $evalWarning;
773
+ $mt->Options(Charset => $charset);
774
+ }
775
+ if ($evalWarning) {
776
+ warn $evalWarning;
777
+ } else {
778
+ $setCharset = $mt->Options('Charset');
779
+ }
741
780
  } else {
742
781
  # set internal encoding of specified metadata type
743
782
  my $type = { id3 => 'ID3', iptc => 'IPTC', exif => 'EXIF', filename => 'FileName',
@@ -771,7 +810,7 @@ for (;;) {
771
810
  $msg = Image::ExifTool::Import::ReadCSV(\*CSVFILE, \%database, $forcePrint);
772
811
  close(CSVFILE);
773
812
  } else {
774
- $msg = "Error opening CSV file '$csvFile'";
813
+ $msg = "Error opening CSV file '${csvFile}'";
775
814
  }
776
815
  $msg and Warn("$msg\n");
777
816
  $isWriting = 1;
@@ -820,11 +859,7 @@ for (;;) {
820
859
  next;
821
860
  }
822
861
  if (/^f$/ or $a eq 'forceprint') {
823
- $forcePrint = $mt->Options('MissingTagValue');
824
- unless (defined $forcePrint) {
825
- $forcePrint = '-';
826
- $mt->Options(MissingTagValue => '-');
827
- }
862
+ $forcePrint = 1;
828
863
  next;
829
864
  }
830
865
  if (/^F([-+]?\d*)$/ or /^fixbase([-+]?\d*)$/i) {
@@ -892,16 +927,15 @@ for (;;) {
892
927
  $ignore{$dir} = 1;
893
928
  next;
894
929
  }
895
- if ($a eq 'if') {
930
+ if (/^if(\d*)$/i) {
896
931
  my $cond = shift;
932
+ $fastCondition = $1 if length $1;
897
933
  defined $cond or Error("Expecting expression for -if option\n"), $badCmd=1, next;
934
+ # prevent processing file unnecessarily for simple case of failed '$ok' or 'not $ok'
935
+ $cond =~ /^\s*(not\s*)\$ok\s*$/i and ($1 xor $rtnValPrev) and $failCondition=1;
898
936
  # add to list of requested tags
899
937
  push @requestTags, $cond =~ /\$\{?((?:[-\w]+:)*[-\w?*]+)/g;
900
- if (defined $condition) {
901
- $condition .= " and ($cond)";
902
- } else {
903
- $condition = "($cond)";
904
- }
938
+ push @condition, $cond;
905
939
  next;
906
940
  }
907
941
  if (/^j(son)?(\+?=.*)?$/i) {
@@ -926,7 +960,7 @@ for (;;) {
926
960
  $msg = Image::ExifTool::Import::ReadJSON(\*JSONFILE, \%database, $forcePrint, $chset);
927
961
  close(JSONFILE);
928
962
  } else {
929
- $msg = "Error opening JSON file '$jsonFile'";
963
+ $msg = "Error opening JSON file '${jsonFile}'";
930
964
  }
931
965
  $msg and Warn("$msg\n");
932
966
  $isWriting = 1;
@@ -941,9 +975,9 @@ for (;;) {
941
975
  }
942
976
  /^(k|pause)$/i and $pause = 1, next;
943
977
  (/^l$/ or $a eq 'long') and --$outFormat, next;
944
- (/^L$/ or $a eq 'latin') and $utf8 = 0, $mt->Options(Charset => 'Latin'), next;
978
+ (/^L$/ or $a eq 'latin') and $mt->Options(Charset => 'Latin'), next;
945
979
  if ($a eq 'lang') {
946
- $langOpt = (@ARGV and $ARGV[0] !~ /^-/) ? shift : undef;
980
+ $langOpt = (@ARGV and $ARGV[0] !~ /^(-|\xe2\x88\x92)/) ? shift : undef;
947
981
  if ($langOpt) {
948
982
  # make lower case and use underline as a separator (eg. 'en_ca')
949
983
  $langOpt =~ tr/-A-Z/_a-z/;
@@ -955,9 +989,9 @@ for (;;) {
955
989
  my $langs = "Available languages:\n";
956
990
  $langs .= " $_ - $Image::ExifTool::langName{$_}\n" foreach @Image::ExifTool::langs;
957
991
  $langs =~ tr/_/-/; # display dashes instead of underlines in language codes
958
- $langs = $mt->Decode($langs, 'UTF8');
959
992
  $langs = Image::ExifTool::HTML::EscapeHTML($langs) if $escapeHTML;
960
- $langOpt and Error("Invalid or unsupported language '$langOpt'.\n$langs"), $badCmd=1, next;
993
+ $langs = $mt->Decode($langs, 'UTF8');
994
+ $langOpt and Error("Invalid or unsupported language '${langOpt}'.\n$langs"), $badCmd=1, next;
961
995
  print $langs;
962
996
  $helped = 1;
963
997
  next;
@@ -972,6 +1006,7 @@ for (;;) {
972
1006
  /^(m|ignoreminorerrors)$/i and $mt->Options(IgnoreMinorErrors => 1), next;
973
1007
  /^(n|-printconv)$/i and $mt->Options(PrintConv => 0), next;
974
1008
  /^(-n|printconv)$/i and $mt->Options(PrintConv => 1), next;
1009
+ $a eq 'nop' and $helped=1, next; # undocumented; no operation
975
1010
  if (/^o(ut)?$/i) {
976
1011
  $outOpt = shift;
977
1012
  defined $outOpt or Error("Expected output file or directory name for -o option\n"), $badCmd=1, next;
@@ -1000,7 +1035,7 @@ for (;;) {
1000
1035
  }
1001
1036
  (/^P$/ or $a eq 'preserve') and $preserveTime = 1, next;
1002
1037
  /^password$/i and $mt->Options(Password => shift), next;
1003
- if (/^progress(:.*)?/i) {
1038
+ if (/^progress(:.*)?$/i) {
1004
1039
  if ($1) {
1005
1040
  $windowTitle = substr $1, 1;
1006
1041
  $windowTitle = 'ExifTool %p%%' unless length $windowTitle;
@@ -1032,8 +1067,10 @@ for (;;) {
1032
1067
  /^s(hort)?(\d*)$/i and $outFormat = $2 eq '' ? $outFormat + 1 : $2, next;
1033
1068
  /^scanforxmp$/i and $mt->Options(ScanForXMP => 1), next;
1034
1069
  if (/^sep(arator)?$/i) {
1035
- $listSep = shift;
1070
+ my $sep = $listSep = shift;
1036
1071
  defined $listSep or Error("Expecting list item separator for -sep option\n"), $badCmd=1, next;
1072
+ $sep =~ s/\\(.)/$unescapeChar{$1}||$1/sge; # translate escape sequences
1073
+ (defined $binSep ? $binTerm : $binSep) = $sep;
1037
1074
  $mt->Options(ListSep => $listSep);
1038
1075
  $joinLists = 1;
1039
1076
  # also split when writing values
@@ -1083,12 +1120,7 @@ for (;;) {
1083
1120
  }
1084
1121
  /^t(ab)?$/ and $tabFormat = 1, next;
1085
1122
  if (/^T$/ or $a eq 'table') {
1086
- $tabFormat = 1; $outFormat+=2; ++$quiet;
1087
- $forcePrint = $mt->Options('MissingTagValue');
1088
- unless (defined $forcePrint) {
1089
- $forcePrint = '-';
1090
- $mt->Options(MissingTagValue => '-');
1091
- }
1123
+ $tabFormat = $forcePrint = 1; $outFormat+=2; ++$quiet;
1092
1124
  next;
1093
1125
  }
1094
1126
  if (/^(u)(nknown(2)?)?$/i) {
@@ -1104,7 +1136,7 @@ for (;;) {
1104
1136
  local $SIG{'__WARN__'} = sub { $evalWarning = $_[0] };
1105
1137
  unless (eval "require Image::ExifTool::$module" or
1106
1138
  eval "require $module" or
1107
- eval "require '$module'")
1139
+ eval "require '${module}'")
1108
1140
  {
1109
1141
  Error("Error using module $module\n");
1110
1142
  $badCmd = 1;
@@ -1171,7 +1203,12 @@ for (;;) {
1171
1203
  $mt->Options(Duplicates=>1);
1172
1204
  next;
1173
1205
  }
1174
- /^z(ip)?$/i and $doUnzip = 1, $mt->Options(Compress => 1, Compact => 1), next;
1206
+ if (/^z(ip)?$/i) {
1207
+ $doUnzip = 1;
1208
+ $mt->Options(Compress => 1, XMPShorthand => 1);
1209
+ $mt->Options(Compact => 1) unless $mt->Options('Compact');
1210
+ next;
1211
+ }
1175
1212
  $_ eq '' and push(@files, '-'), $srcStdin = 1, next; # read STDIN
1176
1213
  length $_ eq 1 and $_ ne '*' and Error("Unknown option -$_\n"), $badCmd=1, next;
1177
1214
  if (/^[^<]+(<?)=(.*)/s) {
@@ -1183,7 +1220,7 @@ for (;;) {
1183
1220
  push @newValues, $_;
1184
1221
  if (/^mwg:/i) {
1185
1222
  $useMWG = 1;
1186
- } elsif (/^([-\w]+:)*(filename|directory)\b/i) {
1223
+ } elsif (/^([-\w]+:)*(filename|directory|testname)\b/i) {
1187
1224
  $doSetFileName = 1;
1188
1225
  } elsif (/^([-\w]+:)*(geotag|geotime|geosync)\b/i) {
1189
1226
  if (lc $2 eq 'geotime') {
@@ -1204,14 +1241,14 @@ for (;;) {
1204
1241
  push @{$setTags{$setTagsFile}}, $_;
1205
1242
  if (/>/) {
1206
1243
  $useMWG = 1 if /^(.*>\s*)?mwg:/si;
1207
- if (/\b(filename|directory)#?$/i) {
1244
+ if (/\b(filename|directory|testname)#?$/i) {
1208
1245
  $doSetFileName = 1;
1209
1246
  } elsif (/\bgeotime#?$/i) {
1210
1247
  $addGeotime = '';
1211
1248
  }
1212
1249
  } else {
1213
1250
  $useMWG = 1 if /^([^<]+<\s*(.*\$\{?)?)?mwg:/si;
1214
- if (/^([-\w]+:)*(filename|directory)\b/i) {
1251
+ if (/^([-\w]+:)*(filename|directory|testname)\b/i) {
1215
1252
  $doSetFileName = 1;
1216
1253
  } elsif (/^([-\w]+:)*geotime\b/i) {
1217
1254
  $addGeotime = '';
@@ -1220,7 +1257,7 @@ for (;;) {
1220
1257
  } else {
1221
1258
  my $lst = s/^-// ? \@exclude : \@tags;
1222
1259
  unless (/^([-\w*]+:)*([-\w*?]+)#?$/) {
1223
- Warn(qq(Invalid TAG name: $_\n));
1260
+ Warn(qq(Invalid TAG name: "$_"\n));
1224
1261
  }
1225
1262
  push @$lst, $_; # (push everything for backward compatibility)
1226
1263
  }
@@ -1246,6 +1283,9 @@ for (;;) {
1246
1283
  }
1247
1284
  }
1248
1285
 
1286
+ # set "OK" UserParam based on result of last command
1287
+ $mt->Options(UserParam => 'OK=' . (not $rtnValPrev));
1288
+
1249
1289
  # set verbose output to STDERR if output could be to console
1250
1290
  $vout = \*STDERR if $srcStdin and ($isWriting or @newValues);
1251
1291
  $mt->Options(TextOut => $vout) if $vout eq \*STDERR;
@@ -1314,15 +1354,22 @@ if ($tagOut and ($csv or %printFmt or $tabFormat or $xml or ($verbose and $html)
1314
1354
  next;
1315
1355
  }
1316
1356
 
1317
- if ($csv and $csv eq 'CSV' and not $isWriting and ($textOut or $binaryOutput)) {
1318
- Warn 'Sorry, ' . ($textOut ? '-w' : '-b') . " may not be combined with -csv\n";
1319
- $rtnVal = 1;
1320
- next;
1357
+ if ($csv and $csv eq 'CSV' and not $isWriting) {
1358
+ if ($textOut) {
1359
+ Warn "Sorry, -w may not be combined with -csv\n";
1360
+ $rtnVal = 1;
1361
+ next;
1362
+ }
1363
+ if ($binaryOutput) {
1364
+ $binaryOutput = 0;
1365
+ $setCharset = 'default' unless defined $setCharset;
1366
+ }
1367
+ require Image::ExifTool::XMP if $setCharset;
1321
1368
  }
1322
1369
 
1323
1370
  if ($escapeHTML or $json) {
1324
1371
  # must be UTF8 for HTML conversion and JSON output
1325
- $mt->Options(Charset => 'UTF8');
1372
+ $mt->Options(Charset => 'UTF8') if $json;
1326
1373
  # use Escape option to do our HTML escaping unless XML output
1327
1374
  $mt->Options(Escape => 'HTML') if $escapeHTML and not $xml;
1328
1375
  } elsif ($escapeXML and not $xml) {
@@ -1470,7 +1517,7 @@ if (@newValues) {
1470
1517
  /(.*?)=(.*)/s or next;
1471
1518
  my ($tag, $newVal) = ($1, $2);
1472
1519
  $tag =~ s/\ball\b/\*/ig; # replace 'all' with '*' in tag names
1473
- $newVal eq '' and undef $newVal; # undefined to delete tag
1520
+ $newVal eq '' and undef $newVal unless $tag =~ s/\^([-+]*)$/$1/; # undefined to delete tag
1474
1521
  if ($tag =~ /^(All)?TagsFromFile$/i) {
1475
1522
  defined $newVal or Error("Need file name for -tagsFromFile\n"), next Command;
1476
1523
  ++$isWriting;
@@ -1479,7 +1526,7 @@ if (@newValues) {
1479
1526
  next; # set tags from dynamic file later
1480
1527
  }
1481
1528
  unless ($mt->Exists($newVal) or $newVal eq '-') {
1482
- Warn "File '$newVal' does not exist for -tagsFromFile option\n";
1529
+ Warn "File '${newVal}' does not exist for -tagsFromFile option\n";
1483
1530
  $rtnVal = 1;
1484
1531
  next Command;
1485
1532
  }
@@ -1516,9 +1563,9 @@ if (@newValues) {
1516
1563
  push @dynamicFiles, [ $tag, $newVal, \%opts ];
1517
1564
  ++$isWriting;
1518
1565
  } elsif (defined $result) {
1519
- Warn "Tag '$tag' is not writable\n";
1566
+ Warn "Tag '${tag}' is not writable\n";
1520
1567
  } else {
1521
- Warn "Tag '$tag' does not exist\n";
1568
+ Warn "Tag '${tag}' does not exist\n";
1522
1569
  }
1523
1570
  next;
1524
1571
  }
@@ -1602,8 +1649,12 @@ if ($outOpt) {
1602
1649
  $scanWritable = 1;
1603
1650
  }
1604
1651
 
1652
+ # initialize alternate encoding flag
1653
+ $altEnc = $mt->Options('Charset');
1654
+ undef $altEnc if $altEnc eq 'UTF8';
1655
+
1605
1656
  # set flag to fix description lengths if necessary
1606
- if ($utf8 and $mt->Options('Lang') ne 'en' and eval { require Encode }) {
1657
+ if (not $altEnc and $mt->Options('Lang') ne 'en' and eval { require Encode }) {
1607
1658
  # (note that Unicode::GCString is part of the Unicode::LineBreak package)
1608
1659
  $fixLen = eval { require Unicode::GCString } ? 2 : 1;
1609
1660
  }
@@ -1669,7 +1720,7 @@ if (@dbKeys) {
1669
1720
  if (defined $absPath) {
1670
1721
  $database{$absPath} = $database{$_} unless $database{$absPath};
1671
1722
  if ($verbose and $verbose > 1) {
1672
- print $vout "Imported entry for '$_' (full path: '$absPath')\n";
1723
+ print $vout "Imported entry for '${_}' (full path: '${absPath}')\n";
1673
1724
  }
1674
1725
  }
1675
1726
  }
@@ -1691,6 +1742,9 @@ PrintCSV() if $csv and not $isWriting;
1691
1742
  print $sectTrailer if $sectTrailer and not $textOut;
1692
1743
  print $fileTrailer if $fileTrailer and not $textOut and not $fileHeader;
1693
1744
 
1745
+ my $totWr = $countGoodWr + $countBadWr + $countSameWr + $countCopyWr +
1746
+ $countGoodCr + $countBadCr;
1747
+
1694
1748
  if (defined $deleteOrig) {
1695
1749
 
1696
1750
  # print summary and delete requested files
@@ -1716,7 +1770,7 @@ if (defined $deleteOrig) {
1716
1770
  if ($quiet) {
1717
1771
  # no more messages
1718
1772
  } elsif ($count and not $countGoodWr and not $countBad) {
1719
- printf "%5d original files found\n", $countGoodWr;
1773
+ printf "%5d original files found\n", $countGoodWr; # (this will be 0)
1720
1774
  } elsif ($deleteOrig) {
1721
1775
  printf "%5d original files deleted\n", $countGoodWr if $count;
1722
1776
  printf "%5d originals not deleted due to errors\n", $countBad if $countBad;
@@ -1729,9 +1783,7 @@ if (defined $deleteOrig) {
1729
1783
 
1730
1784
  # print summary
1731
1785
  my $tot = $count + $countBad;
1732
- my $totWr = $countGoodWr + $countBadWr + $countSameWr + $countCopyWr +
1733
- $countGoodCr + $countBadCr;
1734
- if ($countDir or $totWr or $countFailed or $tot > 1 or $textOut or $countLink or $countBadLink) {
1786
+ if ($countDir or $totWr or $countFailed or $tot > 1 or $textOut or %countLink) {
1735
1787
  my $o = (($html or $json or $xml or %printFmt or $csv) and not $textOut) ? \*STDERR : $vout;
1736
1788
  printf($o "%5d directories scanned\n", $countDir) if $countDir;
1737
1789
  printf($o "%5d directories created\n", $countNewDir) if $countNewDir;
@@ -1746,13 +1798,19 @@ if (defined $deleteOrig) {
1746
1798
  printf($o "%5d files could not be read\n", $countBad) if $countBad;
1747
1799
  printf($o "%5d output files created\n", scalar(keys %created)) if $textOut;
1748
1800
  printf($o "%5d output files appended\n", scalar(keys %appended)) if %appended;
1749
- printf($o "%5d hard links created\n", $countLink) if $countLink or $countBadLink;
1750
- printf($o "%5d hard links could not be created\n", $countBadLink) if $countBadLink;
1801
+ printf($o "%5d hard links created\n", $countLink{Hard} || 0) if $countLink{Hard} or $countLink{BadHard};
1802
+ printf($o "%5d hard links could not be created\n", $countLink{BadHard}) if $countLink{BadHard};
1803
+ printf($o "%5d symbolic links created\n", $countLink{Sym} || 0) if $countLink{Sym} or $countLink{BadSym};
1804
+ printf($o "%5d symbolic links could not be created\n", $countLink{BadSym}) if $countLink{BadSym};
1751
1805
  }
1752
1806
  }
1753
1807
 
1754
1808
  # set error status if we had any errors or if all files failed the "-if" condition
1755
- $rtnVal = 1 if $countBadWr or $countBadCr or $countBad or ($countFailed and not $count);
1809
+ if ($countBadWr or $countBadCr or $countBad) {
1810
+ $rtnVal = 1;
1811
+ } elsif ($countFailed and not ($count or $totWr) and not $rtnVal) {
1812
+ $rtnVal = 2;
1813
+ }
1756
1814
 
1757
1815
  # clean up after each command
1758
1816
  Cleanup();
@@ -1761,7 +1819,7 @@ Cleanup();
1761
1819
 
1762
1820
  close STAYOPEN if $stayOpen >= 2;
1763
1821
 
1764
- Exit $rtnVal; # all done
1822
+ Exit $rtnValApp; # all done
1765
1823
 
1766
1824
 
1767
1825
  #------------------------------------------------------------------------------
@@ -1790,6 +1848,11 @@ sub GetImageInfo($$)
1790
1848
  $title =~ s/%([%bfpr])/$lkup{$1}/eg;
1791
1849
  SetWindowTitle($title);
1792
1850
  }
1851
+ unless (length $orig or $outOpt) {
1852
+ Warn qq(Error: Zero-length file name - ""\n);
1853
+ ++$countBad;
1854
+ return;
1855
+ }
1793
1856
  # determine the name of the source file based on the original input file name
1794
1857
  if (@srcFmt) {
1795
1858
  my ($fmt, $first);
@@ -1815,37 +1878,49 @@ sub GetImageInfo($$)
1815
1878
  }
1816
1879
  }
1817
1880
  # evaluate -if expression for conditional processing
1818
- if (defined $condition) {
1881
+ if (@condition) {
1819
1882
  unless ($file eq '-' or $et->Exists($file)) {
1820
- Warn "File not found: $file\n";
1883
+ Warn "Error: File not found - $file\n";
1821
1884
  FileNotFound($file);
1822
1885
  ++$countBad;
1823
1886
  return;
1824
1887
  }
1825
- # catch run time errors as well as compile errors
1826
- undef $evalWarning;
1827
- local $SIG{'__WARN__'} = sub { $evalWarning = $_[0] };
1828
-
1829
- my %info;
1830
- # extract information and build expression for evaluation
1831
- my $opts = { Duplicates => 1, RequestTags => \@requestTags, Verbose => 0, HtmlDump => 0 };
1832
- # return all tags but explicitly mention tags on command line so
1833
- # requested images will generate the appropriate warnings
1834
- @foundTags = ('*', @tags) if @tags;
1835
- $info = $et->ImageInfo(Infile($pipe,$isWriting), \@foundTags, $opts);
1836
- my $cond = $et->InsertTagValues(\@foundTags, $condition, \%info);
1837
-
1838
- #### eval "-if" condition (%info)
1839
- my $result = eval $cond;
1840
-
1841
- $@ and $evalWarning = $@;
1842
- if ($evalWarning) {
1843
- # fail condition if warning is issued
1844
- undef $result;
1845
- if ($verbose) {
1846
- chomp $evalWarning;
1847
- $evalWarning =~ s/ at \(eval .*//s;
1848
- Warn "Condition: $evalWarning - $file\n";
1888
+ my $result;
1889
+
1890
+ unless ($failCondition) {
1891
+ # catch run time errors as well as compile errors
1892
+ undef $evalWarning;
1893
+ local $SIG{'__WARN__'} = sub { $evalWarning = $_[0] };
1894
+
1895
+ my (%info, $condition);
1896
+ # extract information and build expression for evaluation
1897
+ my $opts = { Duplicates => 1, RequestTags => \@requestTags, Verbose => 0, HtmlDump => 0 };
1898
+ $$opts{FastScan} = $fastCondition if defined $fastCondition;
1899
+ # return all tags but explicitly mention tags on command line so
1900
+ # requested images will generate the appropriate warnings
1901
+ @foundTags = ('*', @tags) if @tags;
1902
+ $info = $et->ImageInfo(Infile($pipe,$isWriting), \@foundTags, $opts);
1903
+ foreach $condition (@condition) {
1904
+ my $cond = $et->InsertTagValues(\@foundTags, $condition, \%info);
1905
+ {
1906
+ # set package so eval'd functions are in Image::ExifTool namespace
1907
+ package Image::ExifTool;
1908
+
1909
+ #### eval "-if" condition (%info)
1910
+ $result = eval $cond;
1911
+
1912
+ $@ and $evalWarning = $@;
1913
+ }
1914
+ if ($evalWarning) {
1915
+ # fail condition if warning is issued
1916
+ undef $result;
1917
+ if ($verbose) {
1918
+ chomp $evalWarning;
1919
+ $evalWarning =~ s/ at \(eval .*//s;
1920
+ Warn "Condition: $evalWarning - $file\n";
1921
+ }
1922
+ }
1923
+ last unless $result;
1849
1924
  }
1850
1925
  }
1851
1926
  unless ($result) {
@@ -1855,7 +1930,7 @@ sub GetImageInfo($$)
1855
1930
  }
1856
1931
  # can't make use of $info if verbose because we must reprocess
1857
1932
  # the file anyway to generate the verbose output
1858
- undef $info if $verbose;
1933
+ undef $info if $verbose or defined $fastCondition;
1859
1934
  }
1860
1935
  if (defined $deleteOrig) {
1861
1936
  print $vout "======== $file$progStr\n" if defined $verbose;
@@ -1909,7 +1984,7 @@ sub GetImageInfo($$)
1909
1984
 
1910
1985
  # extract information from this file
1911
1986
  unless ($file eq '-' or $et->Exists($file)) {
1912
- Warn "File not found: $file\n";
1987
+ Warn "Error: File not found - $file\n";
1913
1988
  FileNotFound($file);
1914
1989
  $outfile and close($fp), undef($tmpText), $et->Unlink($outfile);
1915
1990
  ++$countBad;
@@ -1986,29 +2061,37 @@ sub GetImageInfo($$)
1986
2061
  # print the results for this file
1987
2062
  if (%printFmt) {
1988
2063
  # output using print format file (-p) option
1989
- my ($type, $doc, $grp);
2064
+ my ($type, $doc, $grp, $lastDoc, $cache);
1990
2065
  $fileTrailer = '';
1991
2066
  # repeat for each embedded document if necessary
1992
- my $lastDoc = $et->Options('ExtractEmbedded') ? $$et{DOC_COUNT} : 0;
2067
+ if ($et->Options('ExtractEmbedded')) {
2068
+ # (cache tag keys if there are sub-documents)
2069
+ $lastDoc = $$et{DOC_COUNT} and $cache = { };
2070
+ } else {
2071
+ $lastDoc = 0;
2072
+ }
1993
2073
  for ($doc=0; $doc<=$lastDoc; ++$doc) {
1994
- foreach $type (qw(HEAD SECT BODY ENDS TAIL)) {
2074
+ my $skipBody;
2075
+ foreach $type (qw(HEAD SECT IF BODY ENDS TAIL)) {
1995
2076
  my $prf = $printFmt{$type} or next;
2077
+ next if $type eq 'BODY' and $skipBody;
1996
2078
  if ($lastDoc) {
1997
2079
  if ($doc) {
1998
- next if $type eq 'HEAD' or $type eq 'TAIL'; # only repeat SECT/BODY/ENDS
1999
- $grp = "Doc$doc:";
2080
+ next if $type eq 'HEAD' or $type eq 'TAIL'; # only repeat SECT/IF/BODY/ENDS
2081
+ $grp = "Doc$doc";
2000
2082
  } else {
2001
- $grp = 'Main:';
2083
+ $grp = 'Main';
2002
2084
  }
2003
- # change tag groups to print next document by adding "Main:" or "Doc#:"
2004
- # to all tags which don't already start with a family 3 group name
2005
- $prf = [ @$prf ];
2006
- s/((^|[^\$])(\$\$)*\$\{?)((?!(Main|Doc\d+):)[\w])/$1$grp$4/ig foreach @$prf;
2007
2085
  }
2008
2086
  my @lines;
2087
+ my $opt = $type eq 'IF' ? 'Silent' : 'Warn'; # silence "IF" warnings
2009
2088
  foreach (@$prf) {
2010
- my $line = $et->InsertTagValues(\@foundTags, $_, 'Warn');
2011
- push @lines, $line if defined $line;
2089
+ my $line = $et->InsertTagValues(\@foundTags, $_, $opt, $grp, $cache);
2090
+ if ($type eq 'IF') {
2091
+ $skipBody = 1 unless defined $line;
2092
+ } elsif (defined $line) {
2093
+ push @lines, $line;
2094
+ }
2012
2095
  }
2013
2096
  $lineCount += scalar @lines;
2014
2097
  if ($type eq 'SECT') {
@@ -2044,7 +2127,7 @@ sub GetImageInfo($$)
2044
2127
  } elsif ($xml) {
2045
2128
  my $f = $file;
2046
2129
  CleanXML(\$f);
2047
- print $fp "\n<rdf:Description rdf:about='$f'";
2130
+ print $fp "\n<rdf:Description rdf:about='${f}'";
2048
2131
  print $fp "\n xmlns:et='http://ns.exiftool.ca/1.0/'";
2049
2132
  print $fp " et:toolkit='Image::ExifTool $Image::ExifTool::VERSION'";
2050
2133
  # define namespaces for all tag groups
@@ -2115,7 +2198,7 @@ TAG: foreach $tag (@foundTags) {
2115
2198
  $valList = $val;
2116
2199
  $val = shift @$valList;
2117
2200
  } else {
2118
- $val = join "\n", @$val;
2201
+ $val = join defined $binSep ? $binSep : "\n", @$val;
2119
2202
  }
2120
2203
  } elsif ($joinLists) {
2121
2204
  $val = join $listSep, @$val;
@@ -2182,6 +2265,7 @@ TAG: foreach $tag (@foundTags) {
2182
2265
  # write binary output
2183
2266
  if ($binaryOutput) {
2184
2267
  print $fp $val;
2268
+ print $fp $binTerm if defined $binTerm;
2185
2269
  if ($tagOut) {
2186
2270
  if ($append) {
2187
2271
  $appended{$outfile} = 1 unless $created{$outfile};
@@ -2233,22 +2317,22 @@ TAG: foreach $tag (@foundTags) {
2233
2317
  if ($xml) {
2234
2318
  # RDF/XML output format
2235
2319
  my $tok = "$group:$tagName";
2236
- # manually un-do CR/LF conversion in Windows because output
2237
- # is in text mode, which will re-convert newlines to CR/LF
2238
- $isCRLF and $val =~ s/\x0d\x0a/\x0a/g;
2239
2320
  if ($outFormat > 0) {
2240
2321
  if ($structOpt and ref $val) {
2241
2322
  $val = Image::ExifTool::XMP::SerializeStruct($val);
2242
2323
  }
2243
2324
  if ($escapeHTML) {
2244
2325
  $val =~ tr/\0-\x08\x0b\x0c\x0e-\x1f/./;
2245
- Image::ExifTool::XMP::FixUTF8(\$val) if $utf8;
2246
- $val = Image::ExifTool::HTML::EscapeHTML($val);
2326
+ Image::ExifTool::XMP::FixUTF8(\$val) unless $altEnc;
2327
+ $val = Image::ExifTool::HTML::EscapeHTML($val, $altEnc);
2247
2328
  } else {
2248
2329
  CleanXML(\$val);
2249
2330
  }
2250
2331
  unless ($noDups{$tok}) {
2251
- print $fp "\n $tok='$val'";
2332
+ # manually un-do CR/LF conversion in Windows because output
2333
+ # is in text mode, which will re-convert newlines to CR/LF
2334
+ $isCRLF and $val =~ s/\x0d\x0a/\x0a/g;
2335
+ print $fp "\n $tok='${val}'";
2252
2336
  # XML does not allow duplicate attributes
2253
2337
  $noDups{$tok} = 1;
2254
2338
  }
@@ -2262,20 +2346,23 @@ TAG: foreach $tag (@foundTags) {
2262
2346
  } else {
2263
2347
  $id = Image::ExifTool::XMP::FullEscapeXML($id);
2264
2348
  }
2265
- $xtra = " et:id='$id'";
2266
- $xtra .= " xml:lang='$lang'" if $lang;
2349
+ $xtra = " et:id='${id}'";
2350
+ $xtra .= " xml:lang='${lang}'" if $lang;
2267
2351
  } else {
2268
2352
  $xtra = '';
2269
2353
  }
2270
2354
  if ($tabFormat) {
2271
2355
  my $table = $et->GetTableName($tag);
2272
2356
  my $index = $et->GetTagIndex($tag);
2273
- $xtra .= " et:table='$table'";
2274
- $xtra .= " et:index='$index'" if defined $index;
2357
+ $xtra .= " et:table='${table}'";
2358
+ $xtra .= " et:index='${index}'" if defined $index;
2275
2359
  }
2276
2360
  my $lastVal = $val;
2277
2361
  for ($valNum=0; $valNum<2; ++$valNum) {
2278
2362
  $val = FormatXML($val, $ind, $group);
2363
+ # manually un-do CR/LF conversion in Windows because output
2364
+ # is in text mode, which will re-convert newlines to CR/LF
2365
+ $isCRLF and $val =~ s/\x0d\x0a/\x0a/g;
2279
2366
  if ($outFormat >= 0) {
2280
2367
  # normal output format (note: this will give
2281
2368
  # non-standard RDF/XML if there are any attributes)
@@ -2486,7 +2573,8 @@ TAG: foreach $tag (@foundTags) {
2486
2573
  sub SetImageInfo($$$)
2487
2574
  {
2488
2575
  my ($et, $file, $orig) = @_;
2489
- my ($outfile, $restored, $isTemporary, $isStdout, $outType, $tagsFromSrc, $hardLink, $testName);
2576
+ my ($outfile, $restored, $isTemporary, $isStdout, $outType, $tagsFromSrc);
2577
+ my ($hardLink, $symLink, $testName, $sameFile);
2490
2578
  my $infile = $file; # save infile in case we change it again
2491
2579
 
2492
2580
  # clean up old temporary file if necessary
@@ -2510,7 +2598,7 @@ sub SetImageInfo($$$)
2510
2598
  } else {
2511
2599
  $outfile = FilenameSPrintf($outOpt, $orig);
2512
2600
  if ($outfile eq '') {
2513
- Warn "Can't create file with zero-length name from $orig\n";
2601
+ Warn "Error: Can't create file with zero-length name from $orig\n";
2514
2602
  ++$countBadCr;
2515
2603
  return 0;
2516
2604
  }
@@ -2563,7 +2651,7 @@ sub SetImageInfo($$$)
2563
2651
  unless ($isStdout) {
2564
2652
  $outfile = NextUnusedFilename($outfile);
2565
2653
  if ($et->Exists($outfile) and not $doSetFileName) {
2566
- Warn "Error: '$outfile' already exists - $infile\n";
2654
+ Warn "Error: '${outfile}' already exists - $infile\n";
2567
2655
  ++$countBadWr;
2568
2656
  return 0;
2569
2657
  }
@@ -2640,9 +2728,9 @@ sub SetImageInfo($$$)
2640
2728
  }
2641
2729
  $et->Options(Charset => $old) if $csv eq 'JSON';
2642
2730
  unless ($found) {
2643
- Warn("No SourceFile '$file' in imported $csv database\n");
2731
+ Warn("No SourceFile '${file}' in imported $csv database\n");
2644
2732
  my $absPath = AbsPath($file);
2645
- Warn("(full path: '$absPath')\n") if defined $absPath and $absPath ne $file;
2733
+ Warn("(full path: '${absPath}')\n") if defined $absPath and $absPath ne $file;
2646
2734
  return 0;
2647
2735
  }
2648
2736
  }
@@ -2658,15 +2746,21 @@ sub SetImageInfo($$$)
2658
2746
  } else {
2659
2747
  # get name of hard link if we are creating one
2660
2748
  $hardLink = $et->GetNewValues('HardLink');
2749
+ $symLink = $et->GetNewValues('SymLink');
2661
2750
  $testName = $et->GetNewValues('TestName');
2662
2751
  $hardLink = FilenameSPrintf($hardLink, $orig) if defined $hardLink;
2752
+ $symLink = FilenameSPrintf($symLink, $orig) if defined $symLink;
2753
+ # determine what our output file name should be
2754
+ my $newFileName = $et->GetNewValues('FileName');
2755
+ my $newDir = $et->GetNewValues('Directory');
2663
2756
  if (defined $testName) {
2757
+ my $err;
2758
+ $err = "You shouldn't write FileName or Directory with TestFile" if defined $newFileName or defined $newDir;
2759
+ $err = "The -o option shouldn't be used with TestFile" if defined $outfile;
2760
+ $err and Warn("Error: $err - $infile\n"), ++$countBadWr, return 0;
2664
2761
  $testName = FilenameSPrintf($testName, $orig);
2665
2762
  $testName = Image::ExifTool::GetNewFileName($file, $testName) if $file ne '';
2666
2763
  }
2667
- # determine what our output file name should be
2668
- my $newFileName = $et->GetNewValues('FileName');
2669
- my $newDir = $et->GetNewValues('Directory');
2670
2764
  if (defined $newFileName or defined $newDir or ($doSetFileName and defined $outfile)) {
2671
2765
  if ($newFileName) {
2672
2766
  $newFileName = FilenameSPrintf($newFileName, $orig);
@@ -2683,16 +2777,20 @@ sub SetImageInfo($$$)
2683
2777
  }
2684
2778
  $outfile = NextUnusedFilename($outfile, $infile);
2685
2779
  if ($et->Exists($outfile)) {
2686
- if ($infile ne $outfile) {
2687
- Warn "Error: '$outfile' already exists - $infile\n";
2780
+ if ($infile eq $outfile) {
2781
+ undef $outfile; # not changing the file name after all
2782
+ # (allow for case-insensitive filesystems)
2783
+ } elsif ($et->IsSameFile($infile, $outfile)) {
2784
+ $sameFile = $outfile; # same file, but the name has a different case
2785
+ } else {
2786
+ Warn "Error: '${outfile}' already exists - $infile\n";
2688
2787
  ++$countBadWr;
2689
2788
  return 0;
2690
2789
  }
2691
- undef $outfile; # not changing the file name after all
2692
2790
  }
2693
2791
  }
2694
2792
  if (defined $outfile) {
2695
- $verbose and print $vout "'$infile' --> '$outfile'\n";
2793
+ $verbose and print $vout "'${infile}' --> '${outfile}'\n";
2696
2794
  # create output directory if necessary
2697
2795
  CreateDirectory($outfile);
2698
2796
  # set temporary file (automatically erased on abnormal exit)
@@ -2722,7 +2820,7 @@ sub SetImageInfo($$$)
2722
2820
  }
2723
2821
  } else {
2724
2822
  # file doesn't exist, and we can't create it
2725
- Warn("Error: File not found - $file\n");
2823
+ Warn "Error: File not found - $file\n";
2726
2824
  FileNotFound($file);
2727
2825
  ++$countBadWr;
2728
2826
  return 0;
@@ -2742,13 +2840,13 @@ sub SetImageInfo($$$)
2742
2840
  } else {
2743
2841
  ++$countSameWr;
2744
2842
  }
2745
- if (defined $hardLink or defined $testName) {
2843
+ if (defined $hardLink or defined $symLink or defined $testName) {
2746
2844
  my $src = (defined $outfile and $r4 > 0) ? $outfile : $file;
2747
- DoHardLink($et, $src, $hardLink, $testName);
2845
+ DoHardLink($et, $src, $hardLink, $symLink, $testName);
2748
2846
  }
2749
2847
  return 1;
2750
2848
  }
2751
- unless (defined $outfile) {
2849
+ if (not defined $outfile or defined $sameFile) {
2752
2850
  # write to a truly temporary file
2753
2851
  $outfile = "${file}_exiftool_tmp";
2754
2852
  if ($et->Exists($outfile)) {
@@ -2766,9 +2864,9 @@ sub SetImageInfo($$$)
2766
2864
  my $success = $et->WriteInfo(Infile($file), $outfile, $outType);
2767
2865
 
2768
2866
  # create hard link if specified
2769
- if ($success and (defined $hardLink or defined $testName)) {
2867
+ if ($success and (defined $hardLink or defined $symLink or defined $testName)) {
2770
2868
  my $src = defined $outfile ? $outfile : $file;
2771
- DoHardLink($et, $src, $hardLink, $testName);
2869
+ DoHardLink($et, $src, $hardLink, $symLink, $testName);
2772
2870
  }
2773
2871
 
2774
2872
  # get file time if preserving it
@@ -2806,6 +2904,7 @@ sub SetImageInfo($$$)
2806
2904
  return 0;
2807
2905
  }
2808
2906
  }
2907
+ my $dstFile = defined $sameFile ? $sameFile : $file;
2809
2908
  if ($overwriteOrig > 1) {
2810
2909
  # copy temporary file over top of original to preserve attributes
2811
2910
  my ($err, $buff);
@@ -2829,7 +2928,10 @@ sub SetImageInfo($$$)
2829
2928
  unless ($et->Rename($newFile, $file) or
2830
2929
  ($et->Unlink($file) and $et->Rename($newFile, $file)))
2831
2930
  {
2832
- Error("Error renaming $newFile to $file\n"), return 0;
2931
+ Error("Error renaming $newFile to $file\n");
2932
+ undef $critical;
2933
+ SigInt() if $interrupted;
2934
+ return 0;
2833
2935
  }
2834
2936
  } else {
2835
2937
  $et->SetFileModifyDate($file, $cTime, 'FileCreateDate', 1);
@@ -2854,19 +2956,19 @@ sub SetImageInfo($$$)
2854
2956
 
2855
2957
  # simply rename temporary file to replace original
2856
2958
  # (if we didn't already rename it to add "_original")
2857
- } elsif ($et->Rename($tmpFile, $file)) {
2959
+ } elsif ($et->Rename($tmpFile, $dstFile)) {
2858
2960
  ++$countGoodWr;
2859
2961
  } else {
2860
2962
  my $newFile = $tmpFile;
2861
2963
  undef $tmpFile; # (avoid deleting file if we get interrupted)
2862
2964
  # unlink may fail if already renamed or no permission
2863
2965
  if (not $et->Unlink($file)) {
2864
- Warn "Error renaming temporary file to $file\n";
2966
+ Warn "Error renaming temporary file to $dstFile\n";
2865
2967
  $et->Unlink($newFile);
2866
2968
  ++$countBadWr;
2867
2969
  # try renaming again now that the target has been deleted
2868
- } elsif (not $et->Rename($newFile, $file)) {
2869
- Warn "Error renaming temporary file to $file\n";
2970
+ } elsif (not $et->Rename($newFile, $dstFile)) {
2971
+ Warn "Error renaming temporary file to $dstFile\n";
2870
2972
  # (don't delete tmp file now because it is all we have left)
2871
2973
  ++$countBadWr;
2872
2974
  } else {
@@ -2910,24 +3012,34 @@ sub SetImageInfo($$$)
2910
3012
 
2911
3013
  #------------------------------------------------------------------------------
2912
3014
  # Make hard link and handle TestName if specified
2913
- # Inputs: 0) ExifTool ref, 1) source file name, 2) HardLink name, 3) TestFile name
2914
- sub DoHardLink($$$$)
3015
+ # Inputs: 0) ExifTool ref, 1) source file name, 2) HardLink name,
3016
+ # 3) SymLink name, 4) TestFile name
3017
+ sub DoHardLink($$$$$)
2915
3018
  {
2916
- my ($et, $src, $hardLink, $testName) = @_;
3019
+ my ($et, $src, $hardLink, $symLink, $testName) = @_;
2917
3020
  if (defined $hardLink) {
2918
3021
  $hardLink = NextUnusedFilename($hardLink);
2919
3022
  if ($et->SetFileName($src, $hardLink, 'Link') > 0) {
2920
- ++$countLink;
3023
+ $countLink{Hard} = ($countLink{Hard} || 0) + 1;
3024
+ } else {
3025
+ $countLink{BadHard} = ($countLink{BadHard} || 0) + 1;
3026
+ }
3027
+ }
3028
+ if (defined $symLink) {
3029
+ $symLink = NextUnusedFilename($symLink);
3030
+ if ($et->SetFileName($src, $symLink, 'SymLink') > 0) {
3031
+ $countLink{Sym} = ($countLink{Sym} || 0) + 1;
2921
3032
  } else {
2922
- ++$countBadLink;
3033
+ $countLink{BadSym} = ($countLink{BadSym} || 0) + 1;
2923
3034
  }
2924
3035
  }
2925
3036
  if (defined $testName) {
2926
- $testName = NextUnusedFilename($testName, undef, 1);
3037
+ $testName = NextUnusedFilename($testName, $src, 1);
2927
3038
  if ($usedFileName{$testName}) {
2928
- $et->Warn("File '$testName' would exist");
2929
- } elsif ($et->SetFileName($src, $testName, 'Test') == 1) {
3039
+ $et->Warn("File '${testName}' would exist");
3040
+ } elsif ($et->SetFileName($src, $testName, 'Test', $usedFileName{$testName}) == 1) {
2930
3041
  $usedFileName{$testName} = 1;
3042
+ $usedFileName{$src} = 0;
2931
3043
  }
2932
3044
  }
2933
3045
  }
@@ -2942,7 +3054,7 @@ sub CleanXML($)
2942
3054
  # translate control characters that are invalid in XML
2943
3055
  $$strPt =~ tr/\0-\x08\x0b\x0c\x0e-\x1f/./;
2944
3056
  # fix malformed UTF-8 characters
2945
- Image::ExifTool::XMP::FixUTF8($strPt) if $utf8;
3057
+ Image::ExifTool::XMP::FixUTF8($strPt) unless $altEnc;
2946
3058
  # escape necessary characters for XML
2947
3059
  $$strPt = Image::ExifTool::XMP::EscapeXML($$strPt);
2948
3060
  }
@@ -2955,13 +3067,13 @@ sub EncodeXML($)
2955
3067
  {
2956
3068
  my $strPt = shift;
2957
3069
  if ($$strPt =~ /[\0-\x08\x0b\x0c\x0e-\x1f]/ or
2958
- ($utf8 and Image::ExifTool::XMP::IsUTF8($strPt) < 0))
3070
+ (not $altEnc and Image::ExifTool::XMP::IsUTF8($strPt) < 0))
2959
3071
  {
2960
3072
  # encode binary data and non-UTF8 with special characters as base64
2961
3073
  $$strPt = Image::ExifTool::XMP::EncodeBase64($$strPt);
2962
3074
  return 'http://www.w3.org/2001/XMLSchema#base64Binary'; #ATV
2963
3075
  } elsif ($escapeHTML) {
2964
- $$strPt = Image::ExifTool::HTML::EscapeHTML($$strPt);
3076
+ $$strPt = Image::ExifTool::HTML::EscapeHTML($$strPt, $altEnc);
2965
3077
  } else {
2966
3078
  $$strPt = Image::ExifTool::XMP::EscapeXML($$strPt);
2967
3079
  }
@@ -2996,7 +3108,7 @@ sub FormatXML($$$)
2996
3108
  } else {
2997
3109
  # (note: SCALAR reference should have already been converted)
2998
3110
  my $enc = EncodeXML(\$val);
2999
- $gt = " rdf:datatype='$enc'>\n" if $enc; #ATV
3111
+ $gt = " rdf:datatype='${enc}'>\n" if $enc; #ATV
3000
3112
  }
3001
3113
  return $gt . $val;
3002
3114
  }
@@ -3016,17 +3128,18 @@ sub EscapeJSON($;$)
3016
3128
  # (these big numbers caused problems for some JSON parsers, so be more conservative)
3017
3129
  return $str if $str =~ /^-?(\d|[1-9]\d{1,14})(\.\d{1,16})?(e[-+]?\d{1,3})?$/i;
3018
3130
  }
3019
- # encode JSON string as Base64 if necessary
3131
+ # encode JSON string in base64 if necessary
3020
3132
  if ($json < 2 and defined $binaryOutput and Image::ExifTool::XMP::IsUTF8(\$str) < 0) {
3021
3133
  return '"base64:' . Image::ExifTool::XMP::EncodeBase64($str, 1) . '"';
3022
3134
  }
3135
+ $str =~ s/\0+$//; # remove trailing nulls
3023
3136
  # escape special characters
3024
3137
  $str =~ s/(["\t\n\r\\])/\\$jsonChar{$1}/sg;
3025
3138
  if ($json < 2) { # JSON
3026
3139
  # escape other control characters with \u
3027
3140
  $str =~ s/([\0-\x1f])/sprintf("\\u%.4X",ord $1)/sge;
3028
3141
  # JSON strings must be valid UTF8
3029
- Image::ExifTool::XMP::FixUTF8(\$str) if $utf8;
3142
+ Image::ExifTool::XMP::FixUTF8(\$str) unless $altEnc;
3030
3143
  } else { # PHP
3031
3144
  # must escape "$" too for PHP
3032
3145
  $str =~ s/\$/\\\$/sg;
@@ -3087,6 +3200,12 @@ sub FormatJSON($$$)
3087
3200
  sub FormatCSV($)
3088
3201
  {
3089
3202
  my $val = shift;
3203
+ # check for valid encoding if the Charset option was used
3204
+ if ($setCharset and ($val =~ /[^\x09\x0a\x0d\x20-\x7e\x80-\xff]/ or
3205
+ ($setCharset eq 'UTF8' and Image::ExifTool::XMP::IsUTF8(\$val) < 0)))
3206
+ {
3207
+ $val = 'base64:' . Image::ExifTool::XMP::EncodeBase64($val, 1);
3208
+ }
3090
3209
  # currently, the value may contain NULL characters. It is unclear
3091
3210
  # whether or not this is valid CSV, but some readers may not like it.
3092
3211
  # (if this becomes a problem, in the future values may need to be truncated at
@@ -3163,7 +3282,7 @@ sub ConvertBinary($)
3163
3282
  # (binaryOutput flag is set to 0 for binary mode of XML/PHP/JSON output formats)
3164
3283
  if (defined $binaryOutput) {
3165
3284
  $obj = $$obj;
3166
- # encode in base64 if necessary
3285
+ # encode in base64 if necessary (0xf7 allows for up to 21-bit UTF-8 code space)
3167
3286
  if ($json == 1 and ($obj =~ /[^\x09\x0a\x0d\x20-\x7e\x80-\xf7]/ or
3168
3287
  Image::ExifTool::XMP::IsUTF8(\$obj) < 0))
3169
3288
  {
@@ -3171,7 +3290,7 @@ sub ConvertBinary($)
3171
3290
  }
3172
3291
  } else {
3173
3292
  # (-b is not valid for HTML output)
3174
- my $bOpt = ($html or ($csv and $csv eq 'CSV')) ? '' : ', use -b option to extract';
3293
+ my $bOpt = $html ? '' : ', use -b option to extract';
3175
3294
  if ($$obj =~ /^Binary data \d+ bytes$/) {
3176
3295
  $obj = "($$obj$bOpt)";
3177
3296
  } else {
@@ -3344,7 +3463,7 @@ sub ProcessFiles($;$)
3344
3463
  $filtered = 1;
3345
3464
  $verbose and print $vout "-------- $file (wrong extension)$progStr\n";
3346
3465
  } else {
3347
- Warn "File not found: $file\n";
3466
+ Warn "Error: File not found - $file\n";
3348
3467
  FileNotFound($file);
3349
3468
  $rtnVal = 1;
3350
3469
  }
@@ -3378,17 +3497,29 @@ sub ScanDir($$;$)
3378
3497
  $utf8Name = 1;
3379
3498
  }
3380
3499
  return if $ignore{$dir};
3500
+ my $oldBase = $seqFileBase;
3501
+ $seqFileBase = $seqFileNum;
3381
3502
  # use Win32::FindFile on Windows if available
3382
3503
  # (ReadDir will croak if there is a wildcard, so check for this)
3383
3504
  if ($^O eq 'MSWin32' and $dir !~ /[*?]/) {
3505
+ undef $evalWarning;
3384
3506
  local $SIG{'__WARN__'} = sub { $evalWarning = $_[0] };;
3385
3507
  if (CheckUTF8($dir, $enc) >= 0) {
3386
3508
  if (eval { require Win32::FindFile }) {
3387
- @fileList = Win32::FindFile::ReadDir($dir);
3388
- $_ = $_->cFileName foreach @fileList;
3389
- $et->Options(CharsetFileName => 'UTF8'); # now using UTF8
3390
- $utf8Name = 1; # ReadDir returns UTF-8 file names
3391
- $done = 1;
3509
+ eval {
3510
+ @fileList = Win32::FindFile::ReadDir($dir);
3511
+ $_ = $_->cFileName foreach @fileList;
3512
+ };
3513
+ $@ and $evalWarning = $@;
3514
+ if ($evalWarning) {
3515
+ chomp $evalWarning;
3516
+ $evalWarning =~ s/ at .*//s;
3517
+ Warn "Warning: [Win32::FindFile] $evalWarning - $dir\n";
3518
+ } else {
3519
+ $et->Options(CharsetFileName => 'UTF8'); # now using UTF8
3520
+ $utf8Name = 1; # ReadDir returns UTF-8 file names
3521
+ $done = 1;
3522
+ }
3392
3523
  } else {
3393
3524
  $done = 0;
3394
3525
  }
@@ -3396,7 +3527,11 @@ sub ScanDir($$;$)
3396
3527
  }
3397
3528
  unless ($done) {
3398
3529
  # use standard perl library routines to read directory
3399
- opendir(DIR_HANDLE, $dir) or Warn("Error opening directory $dir\n"), return;
3530
+ unless (opendir(DIR_HANDLE, $dir)) {
3531
+ Warn("Error opening directory $dir\n");
3532
+ $seqFileBase = $oldBase + ($seqFileNum - $seqFileBase);
3533
+ return;
3534
+ }
3400
3535
  @fileList = readdir(DIR_HANDLE);
3401
3536
  closedir(DIR_HANDLE);
3402
3537
  if (defined $done) {
@@ -3449,6 +3584,8 @@ sub ScanDir($$;$)
3449
3584
  }
3450
3585
  ++$countDir;
3451
3586
  $et->Options(CharsetFileName => $enc); # restore original setting
3587
+ # update sequential file base for parent directory
3588
+ $seqFileBase = $oldBase + ($seqFileNum - $seqFileBase);
3452
3589
  }
3453
3590
 
3454
3591
  #------------------------------------------------------------------------------
@@ -3472,23 +3609,35 @@ sub FindFileWindows($$)
3472
3609
  return ();
3473
3610
  }
3474
3611
  CheckUTF8($wildfile, $enc) >= 0 or return ();
3475
- local $SIG{'__WARN__'} = sub { $evalWarning = $_[0] };;
3476
- my @names = Win32::FindFile::FindFile($wildfile) or return ();
3477
- # (apparently this isn't always sorted, so do a case-insensitive sort here)
3478
- @names = sort { uc($a) cmp uc($b) } @names;
3479
- my ($rname, $nm, @files);
3480
- # replace "\?" with ".", and "\*" with ".*" for regular expression
3481
- ($rname = quotemeta $wildname) =~ s/\\\?/./g;
3482
- $rname =~ s/\\\*/.*/g;
3483
- foreach $nm (@names) {
3484
- $nm = $nm->cFileName;
3485
- # make sure that FindFile behaves
3486
- # (otherwise "*.jpg" matches things like "a.jpg_original"!)
3487
- next unless $nm =~ /^$rname$/i;
3488
- next if $nm eq '.' or $nm eq '..'; # don't match "." and ".."
3489
- my $file = "$dir$nm"; # add back directory name
3490
- push @files, $file;
3491
- $utf8FileName{$file} = 1; # flag this file name as UTF-8 encoded
3612
+ undef $evalWarning;
3613
+ local $SIG{'__WARN__'} = sub { $evalWarning = $_[0] };
3614
+ my @files;
3615
+ eval {
3616
+ my @names = Win32::FindFile::FindFile($wildfile) or return;
3617
+ # (apparently this isn't always sorted, so do a case-insensitive sort here)
3618
+ @names = sort { uc($a) cmp uc($b) } @names;
3619
+ my ($rname, $nm);
3620
+ # replace "\?" with ".", and "\*" with ".*" for regular expression
3621
+ ($rname = quotemeta $wildname) =~ s/\\\?/./g;
3622
+ $rname =~ s/\\\*/.*/g;
3623
+ foreach $nm (@names) {
3624
+ $nm = $nm->cFileName;
3625
+ # make sure that FindFile behaves
3626
+ # (otherwise "*.jpg" matches things like "a.jpg_original"!)
3627
+ next unless $nm =~ /^$rname$/i;
3628
+ next if $nm eq '.' or $nm eq '..'; # don't match "." and ".."
3629
+ my $file = "$dir$nm"; # add back directory name
3630
+ push @files, $file;
3631
+ $utf8FileName{$file} = 1; # flag this file name as UTF-8 encoded
3632
+ }
3633
+ };
3634
+ $@ and $evalWarning = $@;
3635
+ if ($evalWarning) {
3636
+ chomp $evalWarning;
3637
+ $evalWarning =~ s/ at .*//s;
3638
+ Warn "Error: [Win32::FindFile] $evalWarning - $wildfile\n";
3639
+ undef @files;
3640
+ ++$countBad;
3492
3641
  }
3493
3642
  return @files;
3494
3643
  }
@@ -3558,7 +3707,7 @@ sub AddPrintFormat($)
3558
3707
  my $expr = shift;
3559
3708
  my $type;
3560
3709
  if ($expr =~ /^#/) {
3561
- $expr =~ s/^#\[(HEAD|SECT|BODY|ENDS|TAIL)\]// or return; # ignore comments
3710
+ $expr =~ s/^#\[(HEAD|SECT|IF|BODY|ENDS|TAIL)\]// or return; # ignore comments
3562
3711
  $type = $1;
3563
3712
  } else {
3564
3713
  $type = 'BODY';
@@ -3593,9 +3742,7 @@ sub SuggestedExtension($$$)
3593
3742
  $ext = 'xml';
3594
3743
  } elsif ($$valPt =~ /^RIFF....WAVE/s) {
3595
3744
  $ext = 'wav';
3596
- } elsif ($tag eq 'OriginalRawFileData' and
3597
- defined($ext = $et->GetValue('OriginalRawFileName')))
3598
- {
3745
+ } elsif ($tag eq 'OriginalRawFileData' and defined($ext = $et->GetValue('OriginalRawFileName'))) {
3599
3746
  $ext =~ s/^.*\.//s;
3600
3747
  $ext = $ext ? lc($ext) : 'raw';
3601
3748
  } elsif ($tag eq 'EXIF') {
@@ -3604,10 +3751,17 @@ sub SuggestedExtension($$$)
3604
3751
  $ext = 'icc';
3605
3752
  } elsif ($$valPt =~ /^(MM\0\x2a|II\x2a\0)/) {
3606
3753
  $ext = 'tiff';
3754
+ } elsif ($$valPt =~ /^.{4}ftyp(3gp|mp4|f4v|qt )/s) {
3755
+ my %movType = ( 'qt ' => 'mov' );
3756
+ $ext = $movType{$1} || $1;
3607
3757
  } elsif ($$valPt !~ /^.{0,4096}\0/s) {
3608
3758
  $ext = 'txt';
3609
- } elsif ($$valPt =~ /^BM/) {
3759
+ } elsif ($$valPt =~ /^BM.{15}\0/s) {
3610
3760
  $ext = 'bmp';
3761
+ } elsif ($$valPt =~ /^CANON OPTIONAL DATA\0/) {
3762
+ $ext = 'vrd';
3763
+ } elsif ($$valPt =~ /^IIII\x04\0\x04\0/) {
3764
+ $ext = 'dr4';
3611
3765
  } else {
3612
3766
  $ext = 'dat';
3613
3767
  }
@@ -3731,34 +3885,39 @@ sub NextUnusedFilename($;$$)
3731
3885
  $filename .= substr($fmt, $pos, pos($fmt) - $pos - length($1));
3732
3886
  $pos = pos($fmt);
3733
3887
  my ($sign, $wid, $dec, $wid2, $mod, $tok) = ($2, $3 || 0, $4, $5 || 0, $6, $7);
3734
- my $diff = 0;
3888
+ my $diff;
3735
3889
  if ($tok eq 'C') {
3736
- $diff = $wid;
3890
+ $diff = $wid - ($sign eq '-' ? $seqFileBase : 0);
3737
3891
  $wid = $wid2;
3738
3892
  } else {
3739
3893
  next unless $dec or $copy;
3740
3894
  $wid = $wid2 if $wid < $wid2;
3895
+ # add dash or underline separator if '-' or '+' specified
3896
+ $filename .= $sep{$sign} if $sign;
3741
3897
  }
3742
- # add dash or underline separator if '-' or '+' specified
3743
- $filename .= $sep{$sign} if $sign;
3744
3898
  if ($mod and $mod ne 'n') {
3745
- my $a = $tok eq 'C' ? Num2Alpha($diff + $seq++) : $alpha;
3899
+ my $a = $tok eq 'C' ? Num2Alpha($diff + $seq) : $alpha;
3746
3900
  my $str = ($wid and $wid > length $a) ? 'a' x ($wid - length($a)) : '';
3747
3901
  $str .= $a;
3748
3902
  $str = uc $str if $mod eq 'u';
3749
3903
  $filename .= $str;
3750
3904
  } else {
3751
- my $c = $tok eq 'C' ? ($diff + $seq++) : $copy;
3905
+ my $c = $tok eq 'C' ? ($diff + $seq) : $copy;
3752
3906
  my $num = $c + ($mod ? 1 : 0);
3753
3907
  $filename .= $wid ? sprintf("%.${wid}d",$num) : $num;
3754
3908
  }
3755
3909
  }
3756
3910
  $filename .= substr($fmt, $pos); # add rest of file name
3757
3911
  # return now with filename unless file exists
3758
- return $filename unless $mt->Exists($filename) or $usedFileName{$filename};
3759
- return $filename if defined $okfile and $filename eq $okfile;
3912
+ return $filename unless ($mt->Exists($filename) and not defined $usedFileName{$filename}) or $usedFileName{$filename};
3913
+ if (defined $okfile) {
3914
+ return $filename if $filename eq $okfile;
3915
+ my ($fn, $ok) = (AbsPath($filename), AbsPath($okfile));
3916
+ return $okfile if defined $fn and defined $ok and $fn eq $ok;
3917
+ }
3760
3918
  ++$copy;
3761
3919
  ++$alpha;
3920
+ ++$seq;
3762
3921
  }
3763
3922
  }
3764
3923
 
@@ -3900,6 +4059,32 @@ sub SlurpFile($$)
3900
4059
  return 1;
3901
4060
  }
3902
4061
 
4062
+
4063
+ #------------------------------------------------------------------------------
4064
+ # Filter argfile line
4065
+ # Inputs: 0) line of argfile
4066
+ # Returns: filtered line or undef to ignore
4067
+ sub FilterArgfileLine($)
4068
+ {
4069
+ my $arg = shift;
4070
+ if ($arg =~ /^#/) { # comment lines begin with '#'
4071
+ return undef unless $arg =~ s/^#\[CSTR\]//;
4072
+ $arg =~ s/[\x0d\x0a]+$//s; # remove trailing newline
4073
+ # escape double quotes, dollar signs and ampersands if they aren't already
4074
+ # escaped by an odd number of backslashes, and escape a single backslash
4075
+ # if it occurs at the end of the string
4076
+ $arg =~ s{\\(.)|(["\$\@]|\\$)}{'\\'.($2 || $1)}sge;
4077
+ $arg = eval qq{"$arg"}; # un-escape characters in C string
4078
+ } else {
4079
+ $arg =~ s/^\s+//; # remove leading white space
4080
+ $arg =~ s/[\x0d\x0a]+$//s; # remove trailing newline
4081
+ # remove white space before, and single space after '=', '+=', '-=' or '<='
4082
+ $arg =~ s/^(-[-:\w]+#?)\s*([-+<]?=) ?/$1$2/;
4083
+ return undef if $arg eq '';
4084
+ }
4085
+ return $arg;
4086
+ }
4087
+
3903
4088
  #------------------------------------------------------------------------------
3904
4089
  # Read arguments from -stay_open argfile
3905
4090
  # Inputs: 0) argument list ref
@@ -3927,11 +4112,8 @@ sub ReadStayOpen($)
3927
4112
  my $len = pos($stayOpenBuff) - $pos;
3928
4113
  my $arg = substr($stayOpenBuff, $pos, $len);
3929
4114
  $pos += $len;
3930
- $arg =~ s/^\s+//; # remove leading white space
3931
- $arg =~ s/[\x0d\x0a]+$//s; # remove trailing newline
3932
- # remove white space before, and single space after '=', '+=', '-=' or '<='
3933
- $arg =~ s/^(-[-:\w]+#?)\s*([-+<]?=) ?/$1$2/;
3934
- next if $arg eq '' or $arg =~ /^#/; # ignore empty/comment lines
4115
+ $arg = FilterArgfileLine($arg);
4116
+ next unless defined $arg;
3935
4117
  push @newArgs, $arg;
3936
4118
  if ($optArgs) {
3937
4119
  # this is an argument for the last option
@@ -4055,12 +4237,12 @@ one or more source file names, directory names, or C<-> for the standard
4055
4237
  input. Metadata is read from source files and printed in readable form to
4056
4238
  the console (or written to output text files with B<-w>).
4057
4239
 
4058
- To write or delete metadata, tag values are assigned using the
4059
- -I<TAG>=[I<VALUE>] syntax, or the B<-geotag> option. To copy or move
4060
- metadata, the B<-tagsFromFile> feature is used. By default the original
4061
- files are preserved with C<_original> appended to their names -- be sure to
4062
- verify that the new files are OK before erasing the originals. Once in
4063
- write mode, exiftool will ignore any read-specific options.
4240
+ To write or delete metadata, tag values are assigned using
4241
+ -I<TAG>=[I<VALUE>], and/or the B<-geotag>, B<-csv=> or B<-json=> options.
4242
+ To copy or move metadata, the B<-tagsFromFile> feature is used. By default
4243
+ the original files are preserved with C<_original> appended to their names
4244
+ -- be sure to verify that the new files are OK before erasing the originals.
4245
+ Once in write mode, exiftool will ignore any read-specific options.
4064
4246
 
4065
4247
  Note: If I<FILE> is a directory name then only supported file types in the
4066
4248
  directory are processed (in write mode only writable types are processed).
@@ -4075,43 +4257,45 @@ supported by ExifTool (r = read, w = write, c = create):
4075
4257
 
4076
4258
  File Types
4077
4259
  ------------+-------------+-------------+-------------+------------
4078
- 3FR r | DVB r/w | JSON r | OFR r | RTF r
4079
- 3G2 r/w | DYLIB r | K25 r | OGG r | RW2 r/w
4080
- 3GP r/w | EIP r | KDC r | OGV r | RWL r/w
4081
- A r | EPS r/w | KEY r | OPUS r | RWZ r
4082
- AA r | EPUB r | LA r | ORF r/w | RM r
4083
- AAX r/w | ERF r/w | LFP r | OTF r | SEQ r
4084
- ACR r | EXE r | LNK r | PAC r | SO r
4085
- AFM r | EXIF r/w/c | M2TS r | PAGES r | SR2 r/w
4086
- AI r/w | EXR r | M4A/V r/w | PBM r/w | SRF r
4087
- AIFF r | EXV r/w/c | MAX r | PCD r | SRW r/w
4088
- APE r | F4A/V r/w | MEF r/w | PDB r | SVG r
4089
- ARW r/w | FFF r/w | MIE r/w/c | PDF r/w | SWF r
4090
- ASF r | FLA r | MIFF r | PEF r/w | THM r/w
4091
- AVI r | FLAC r | MKA r | PFA r | TIFF r/w
4092
- AZW r | FLIF r/w | MKS r | PFB r | TORRENT r
4093
- BMP r | FLV r | MKV r | PFM r | TTC r
4094
- BPG r | FPF r | MNG r/w | PGF r | TTF r
4095
- BTF r | FPX r | MOBI r | PGM r/w | VCF r
4096
- CHM r | GIF r/w | MODD r | PLIST r | VRD r/w/c
4097
- COS r | GZ r | MOI r | PICT r | VSD r
4098
- CR2 r/w | HDP r/w | MOS r/w | PMP r | WAV r
4099
- CRW r/w | HDR r | MOV r/w | PNG r/w | WDP r/w
4100
- CS1 r/w | HEIC r | MP3 r | PPM r/w | WEBP r
4101
- DCM r | HEIF r | MP4 r/w | PPT r | WEBM r
4102
- DCP r/w | HTML r | MPC r | PPTX r | WMA r
4103
- DCR r | ICC r/w/c | MPG r | PS r/w | WMV r
4104
- DFONT r | ICS r | MPO r/w | PSB r/w | WV r
4105
- DIVX r | IDML r | MQV r/w | PSD r/w | X3F r/w
4106
- DJVU r | IIQ r/w | MRW r/w | PSP r | XCF r
4107
- DLL r | IND r/w | MXF r | QTIF r/w | XLS r
4108
- DNG r/w | INX r | NEF r/w | RA r | XLSX r
4109
- DOC r | ISO r | NRW r/w | RAF r/w | XMP r/w/c
4110
- DOCX r | ITC r | NUMBERS r | RAM r | ZIP r
4111
- DPX r | J2C r | O r | RAR r |
4112
- DR4 r/w/c | JNG r/w | ODP r | RAW r/w |
4113
- DSS r | JP2 r/w | ODS r | RIFF r |
4114
- DV r | JPEG r/w | ODT r | RSRC r |
4260
+ 3FR r | DSS r | J2C r | ODP r | RAW r/w
4261
+ 3G2 r/w | DV r | JNG r/w | ODS r | RIFF r
4262
+ 3GP r/w | DVB r/w | JP2 r/w | ODT r | RSRC r
4263
+ A r | DVR-MS r | JPEG r/w | OFR r | RTF r
4264
+ AA r | DYLIB r | JSON r | OGG r | RW2 r/w
4265
+ AAE r | EIP r | K25 r | OGV r | RWL r/w
4266
+ AAX r/w | EPS r/w | KDC r | OPUS r | RWZ r
4267
+ ACR r | EPUB r | KEY r | ORF r/w | RM r
4268
+ AFM r | ERF r/w | LA r | OTF r | SEQ r
4269
+ AI r/w | EXE r | LFP r | PAC r | SKETCH r
4270
+ AIFF r | EXIF r/w/c | LNK r | PAGES r | SO r
4271
+ APE r | EXR r | LRV r/w | PBM r/w | SR2 r/w
4272
+ ARQ r/w | EXV r/w/c | M2TS r | PCD r | SRF r
4273
+ ARW r/w | F4A/V r/w | M4A/V r/w | PCX r | SRW r/w
4274
+ ASF r | FFF r/w | MAX r | PDB r | SVG r
4275
+ AVI r | FITS r | MEF r/w | PDF r/w | SWF r
4276
+ AZW r | FLA r | MIE r/w/c | PEF r/w | THM r/w
4277
+ BMP r | FLAC r | MIFF r | PFA r | TIFF r/w
4278
+ BPG r | FLIF r/w | MKA r | PFB r | TORRENT r
4279
+ BTF r | FLV r | MKS r | PFM r | TTC r
4280
+ CHM r | FPF r | MKV r | PGF r | TTF r
4281
+ COS r | FPX r | MNG r/w | PGM r/w | VCF r
4282
+ CR2 r/w | GIF r/w | MOBI r | PLIST r | VRD r/w/c
4283
+ CR3 r/w | GPR r/w | MODD r | PICT r | VSD r
4284
+ CRM r/w | GZ r | MOI r | PMP r | WAV r
4285
+ CRW r/w | HDP r/w | MOS r/w | PNG r/w | WDP r/w
4286
+ CS1 r/w | HDR r | MOV r/w | PPM r/w | WEBP r
4287
+ DCM r | HEIC r | MP3 r | PPT r | WEBM r
4288
+ DCP r/w | HEIF r | MP4 r/w | PPTX r | WMA r
4289
+ DCR r | HTML r | MPC r | PS r/w | WMV r
4290
+ DFONT r | ICC r/w/c | MPG r | PSB r/w | WTV r
4291
+ DIVX r | ICS r | MPO r/w | PSD r/w | WV r
4292
+ DJVU r | IDML r | MQV r/w | PSP r | X3F r/w
4293
+ DLL r | IIQ r/w | MRW r/w | QTIF r/w | XCF r
4294
+ DNG r/w | IND r/w | MXF r | R3D r | XLS r
4295
+ DOC r | INSV r | NEF r/w | RA r | XLSX r
4296
+ DOCX r | INX r | NRW r/w | RAF r/w | XMP r/w/c
4297
+ DPX r | ISO r | NUMBERS r | RAM r | ZIP r
4298
+ DR4 r/w/c | ITC r | O r | RAR r |
4115
4299
 
4116
4300
  Meta Information
4117
4301
  ----------------------+----------------------+---------------------
@@ -4147,7 +4331,7 @@ options may appear after source file names on the exiftool command line.
4147
4331
  L<Tag operations|/Tag operations>
4148
4332
 
4149
4333
  -TAG or --TAG Extract or exclude specified tag
4150
- -TAG[+-]=[VALUE] Write new value for tag
4334
+ -TAG[+-^]=[VALUE] Write new value for tag
4151
4335
  -TAG[+-]<=DATFILE Write tag value from contents of file
4152
4336
  -TAG[+-]<SRCTAG Copy tag value (see -tagsFromFile)
4153
4337
 
@@ -4160,7 +4344,7 @@ L<Input-output text formatting|/Input-output text formatting>
4160
4344
  -b (-binary) Output metadata in binary format
4161
4345
  -c FMT (-coordFormat) Set format for GPS coordinates
4162
4346
  -charset [[TYPE=]CHARSET] Specify encoding for special characters
4163
- -csv[=CSVFILE] Export/import tags in CSV format
4347
+ -csv[[+]=CSVFILE] Export/import tags in CSV format
4164
4348
  -d FMT (-dateFormat) Set format for date/time values
4165
4349
  -D (-decimal) Show tag ID numbers in decimal
4166
4350
  -E, -ex (-escape(HTML|XML)) Escape values for HTML (-E) or XML (-ex)
@@ -4170,7 +4354,7 @@ L<Input-output text formatting|/Input-output text formatting>
4170
4354
  -h (-htmlFormat) Use HMTL formatting for output
4171
4355
  -H (-hex) Show tag ID numbers in hexadecimal
4172
4356
  -htmlDump[OFFSET] Generate HTML-format binary dump
4173
- -j[=JSONFILE] (-json) Export/import tags in JSON format
4357
+ -j[[+]=JSONFILE] (-json) Export/import tags in JSON format
4174
4358
  -l (-long) Use long 2-line output format
4175
4359
  -L (-latin) Use Windows Latin1 encoding
4176
4360
  -lang [LANG] Set current language
@@ -4201,7 +4385,7 @@ L<Processing control|/Processing control>
4201
4385
  -fast[NUM] Increase speed for slow devices
4202
4386
  -fileOrder [-]TAG Set file processing order
4203
4387
  -i DIR (-ignore) Ignore specified directory name
4204
- -if EXPR Conditionally process files
4388
+ -if[NUM] EXPR Conditionally process files
4205
4389
  -m (-ignoreMinorErrors) Ignore minor errors and warnings
4206
4390
  -o OUTFILE (-out) Set output file or directory name
4207
4391
  -overwrite_original Overwrite original by renaming tmp file
@@ -4237,14 +4421,14 @@ L<Utilities|/Utilities>
4237
4421
 
4238
4422
  L<Advanced options|/Advanced options>
4239
4423
 
4240
- -api OPT[=VAL] Set ExifTool API option
4424
+ -api OPT[[^]=[VAL]] Set ExifTool API option
4241
4425
  -common_args Define common arguments
4242
4426
  -config CFGFILE Specify configuration file name
4243
4427
  -echo[NUM] TEXT Echo text to stdout or stderr
4244
4428
  -execute[NUM] Execute multiple commands on one line
4245
4429
  -srcfile FMT Process a different source file
4246
4430
  -stay_open FLAG Keep reading -@ argfile even after EOF
4247
- -userParam PARAM[=VAL] Set user parameter (API UserParam opt)
4431
+ -userParam PARAM[[^]=[VAL]] Set user parameter (API UserParam opt)
4248
4432
 
4249
4433
  =head2 Option Details
4250
4434
 
@@ -4299,7 +4483,7 @@ group delete (unless a family 2 group is specified, see note 4 below).
4299
4483
  Instead, individual tags may be recovered using the B<-tagsFromFile> option
4300
4484
  (eg. C<-all= -tagsfromfile @ -artist>).
4301
4485
 
4302
- =item B<->I<TAG>[+-]B<=>[I<VALUE>]
4486
+ =item B<->I<TAG>[+-^]B<=>[I<VALUE>]
4303
4487
 
4304
4488
  Write a new value for the specified tag (eg. C<-comment=wow>), or delete the
4305
4489
  tag if no I<VALUE> is given (eg. C<-comment=>). C<+=> and C<-=> are used to
@@ -4307,7 +4491,9 @@ add or remove existing entries from a list, or to shift date/time values
4307
4491
  (see L<Image::ExifTool::Shift.pl|Image::ExifTool::Shift.pl> and note 6 below
4308
4492
  for more details). C<+=> may also be used to increment numerical values (or
4309
4493
  decrement if I<VALUE> is negative), and C<-=> may be used to conditionally
4310
- delete or replace a tag (see L</WRITING EXAMPLES> for examples).
4494
+ delete or replace a tag (see L</WRITING EXAMPLES> for examples). C<^=> is
4495
+ used to write an empty string instead of deleting the tag when no I<VALUE>
4496
+ is given, but otherwise it is equivalent to C<=>.
4311
4497
 
4312
4498
  I<TAG> may contain one or more leading family 0, 1 or 2 group names,
4313
4499
  prefixed by optional family numbers, and separated colons. If no group name
@@ -4321,11 +4507,11 @@ value to multiple tags. When specified with wildcards, "unsafe" tags are
4321
4507
  not written. A tag name of C<All> is equivalent to C<*> (except that it
4322
4508
  doesn't require quoting, while arguments with wildcards do on systems with
4323
4509
  shell globbing), and is often used when deleting all metadata (ie. C<-All=>)
4324
- or an entire group (eg. C<-GROUP:All=>, see note 4 below). Note that not
4510
+ or an entire group (eg. C<-XMP-dc:All=>, see note 4 below). Note that not
4325
4511
  all groups are deletable, and that the JPEG APP14 "Adobe" group is not
4326
4512
  removed by default with C<-All=> because it may affect the appearance of the
4327
- image. However, this will remove color space information, so the colors may
4328
- be affected (but this may be avoided by copying back the tags defined by the
4513
+ image. However, color space information is removed, so the colors may be
4514
+ affected (but this may be avoided by copying back the tags defined by the
4329
4515
  ColorSpaceTags shortcut). Use the B<-listd> option for a complete list of
4330
4516
  deletable groups, and see note 5 below regarding the "APP" groups. Also,
4331
4517
  within an image some groups may be contained within others, and these groups
@@ -4428,22 +4614,23 @@ B<-w> option for I<FMT> string examples.
4428
4614
  A powerful redirection feature allows a destination tag to be specified for
4429
4615
  each copied tag. With this feature, information may be written to a tag
4430
4616
  with a different name or group. This is done using
4431
- E<quot>'-I<DSTTAG>E<lt>I<SRCTAG>'E<quot> or
4617
+ E<quot>'-I<DSTTAG>E<lt>I<SRCTAG>'E<quot> or
4432
4618
  E<quot>'-I<SRCTAG>E<gt>I<DSTTAG>'E<quot> on the command line after
4433
4619
  B<-tagsFromFile>, and causes the value of I<SRCTAG> to be copied from
4434
- I<SRCFILE> and written to I<DSTTAG> in I<FILE>. Note that this argument
4435
- must be quoted to prevent shell redirection, and there is no C<=> sign as
4436
- when assigning new values. Source and/or destination tags may be prefixed
4437
- by a group name and/or suffixed by C<#>. Wildcards are allowed in both the
4438
- source and destination tag names. A destination group and/or tag name of
4439
- C<All> or C<*> writes to the same family 1 group and/or tag name as the
4440
- source. If no destination group is specified, the information is written to
4441
- the preferred group. Whitespace around the C<E<gt>> or C<E<lt>> is ignored.
4442
- As a convenience, C<-tagsFromFile @> is assumed for any redirected tags
4443
- which are specified without a prior B<-tagsFromFile> option. Copied tags
4444
- may also be added or deleted from a list with arguments of the form
4620
+ I<SRCFILE> and written to I<DSTTAG> in I<FILE>. Has no effect unless
4621
+ I<SRCTAG> exists in I<SRCFILE>. Note that this argument must be quoted to
4622
+ prevent shell redirection, and there is no C<=> sign as when assigning new
4623
+ values. Source and/or destination tags may be prefixed by a group name
4624
+ and/or suffixed by C<#>. Wildcards are allowed in both the source and
4625
+ destination tag names. A destination group and/or tag name of C<All> or
4626
+ C<*> writes to the same family 1 group and/or tag name as the source. If no
4627
+ destination group is specified, the information is written to the preferred
4628
+ group. Whitespace around the C<E<gt>> or C<E<lt>> is ignored. As a
4629
+ convenience, C<-tagsFromFile @> is assumed for any redirected tags which are
4630
+ specified without a prior B<-tagsFromFile> option. Copied tags may also be
4631
+ added or deleted from a list with arguments of the form
4445
4632
  E<quot>'-I<SRCTAG>+E<lt>I<DSTTAG>'E<quot> or
4446
- E<quot>'-I<SRCTAG>-E<lt>I<DSTTAG>'E<quot>.
4633
+ E<quot>'-I<SRCTAG>-E<lt>I<DSTTAG>'E<quot> (but see Note 5 below).
4447
4634
 
4448
4635
  An extension of the redirection feature allows strings involving tag names
4449
4636
  to be used on the right hand side of the C<E<lt>> symbol with the syntax
@@ -4519,7 +4706,8 @@ names containing wildcards. When copying directly, the values of each
4519
4706
  matching source tag are copied individually to the destination tag (as if
4520
4707
  they were separate assignments). However, when interpolated inside a
4521
4708
  string, list items and the values of shortcut tags are concatenated (with a
4522
- separator set by the B<-sep> option), and wildcards are not allowed.
4709
+ separator set by the B<-sep> option), and wildcards are not allowed. Also,
4710
+ UserParam variables are available only when interpolated in a string.
4523
4711
 
4524
4712
  =item B<-x> I<TAG> (B<-exclude>)
4525
4713
 
@@ -4564,14 +4752,16 @@ Output requested metadata in binary format without tag names or
4564
4752
  descriptions. This option is mainly used for extracting embedded images or
4565
4753
  other binary data, but it may also be useful for some text strings since
4566
4754
  control characters (such as newlines) are not replaced by '.' as they are in
4567
- the default output. List items are separated by a newline when extracted
4568
- with the B<-b> option. May be combined with C<-j>, C<-php> or C<-X> to
4569
- extract binary data in JSON, PHP or XML format.
4755
+ the default output. By default, list items are separated by a newline when
4756
+ extracted with the B<-b> option, but this may be changed (see the B<-sep>
4757
+ option for details). May be combined with C<-j>, C<-php> or C<-X> to
4758
+ extract binary data in JSON, PHP or XML format, but note that "unsafe" tags
4759
+ must be specified explicitly to be extracted as binary in these formats.
4570
4760
 
4571
4761
  =item B<-c> I<FMT> (B<-coordFormat>)
4572
4762
 
4573
4763
  Set the print format for GPS coordinates. I<FMT> uses the same syntax as
4574
- the C<printf> format string. The specifiers correspond to degrees, minutes
4764
+ a C<printf> format string. The specifiers correspond to degrees, minutes
4575
4765
  and seconds in that order, but minutes and seconds are optional. For
4576
4766
  example, the following table gives the output for the same coordinate using
4577
4767
  various formats:
@@ -4599,9 +4789,8 @@ coordinates as signed decimal degrees.
4599
4789
 
4600
4790
  If I<TYPE> is C<ExifTool> or not specified, this option sets the ExifTool
4601
4791
  character encoding for output tag values when reading and input values when
4602
- writing. The default ExifTool encoding is C<UTF8>. If no I<CHARSET> is
4603
- given, a list of available character sets is returned. Valid I<CHARSET>
4604
- values are:
4792
+ writing, with a default of C<UTF8>. If no I<CHARSET> is given, a list of
4793
+ available character sets is returned. Valid I<CHARSET> values are:
4605
4794
 
4606
4795
  CHARSET Alias(es) Description
4607
4796
  ---------- --------------- ----------------------------------
@@ -4650,7 +4839,7 @@ information about coded character sets, and the
4650
4839
  L<Image::ExifTool Options|Image::ExifTool/Options> for more details about
4651
4840
  the B<-charset> settings.
4652
4841
 
4653
- =item B<-csv>[=I<CSVFILE>]
4842
+ =item B<-csv>[[+]=I<CSVFILE>]
4654
4843
 
4655
4844
  Export information in CSV format, or import information if I<CSVFILE> is
4656
4845
  specified. When importing, the CSV file must be in exactly the same format
@@ -4668,21 +4857,26 @@ The following examples demonstrate basic use of this option:
4668
4857
  # update metadata for all images in a directory from CSV file
4669
4858
  exiftool -csv=a.csv dir
4670
4859
 
4671
- Empty values are ignored when importing. Also, FileName and Directory
4672
- columns are ignored if they exist (ie. ExifTool will not attempt to write
4673
- these tags with a CSV import). To force a tag to be deleted, use the B<-f>
4674
- option and set the value to "-" in the CSV file (or to the MissingTagValue
4675
- if this API option was used). Multiple databases may be imported in a
4676
- single command.
4677
-
4678
- When exporting a CSV file, the B<-g> or B<-G> option to add group names to
4679
- the tag headings. If the B<-a> option is used to allow duplicate tag names,
4680
- the duplicate tags are only included in the CSV output if the column
4681
- headings are unique. Adding the B<-G4> option ensures a unique column
4682
- heading for each tag. When exporting specific tags, the CSV columns are
4683
- arranged in the same order as the specified tags provided the column
4684
- headings exactly match the specified tag names, otherwise the columns are
4685
- sorted in alphabetical order.
4860
+ Empty values are ignored when importing (unless the B<-f> option is used and
4861
+ the API MissingTagValue is set to an empty string, in which case the tag is
4862
+ deleted). Also, FileName and Directory columns are ignored if they exist
4863
+ (ie. ExifTool will not attempt to write these tags with a CSV import). To
4864
+ force a tag to be deleted, use the B<-f> option and set the value to "-" in
4865
+ the CSV file (or to the MissingTagValue if this API option was used).
4866
+ Multiple databases may be imported in a single command.
4867
+
4868
+ When exporting a CSV file, the B<-g> or B<-G> option adds group names to the
4869
+ tag headings. If the B<-a> option is used to allow duplicate tag names, the
4870
+ duplicate tags are only included in the CSV output if the column headings
4871
+ are unique. Adding the B<-G4> option ensures a unique column heading for
4872
+ each tag. The B<-b> option may be added to output binary data, encoded in
4873
+ base64 if necessary (indicated by ASCII "base64:" as the first 7 bytes of
4874
+ the value). Values may also be encoded in base64 if the B<-charset> option
4875
+ is used and the value contains invalid characters.
4876
+
4877
+ When exporting specific tags, the CSV columns are arranged in the same order
4878
+ as the specified tags provided the column headings exactly match the
4879
+ specified tag names, otherwise the columns are sorted in alphabetical order.
4686
4880
 
4687
4881
  When importing from a CSV file, only files specified on the command line are
4688
4882
  processed. Any extra entries in the CSV file are ignored.
@@ -4702,11 +4896,13 @@ option.
4702
4896
 
4703
4897
  =item B<-d> I<FMT> (B<-dateFormat>)
4704
4898
 
4705
- Set the format for date/time tag values. The specifics of the I<FMT> syntax
4899
+ Set the format for date/time tag values. The I<FMT> string may contain
4900
+ formatting codes beginning with a percent character (C<%>) to represent the
4901
+ various components of a date/time value. The specifics of the I<FMT> syntax
4706
4902
  are system dependent -- consult the C<strftime> man page on your system for
4707
4903
  details. The default format is equivalent to "%Y:%m:%d %H:%M:%S". This
4708
4904
  option has no effect on date-only or time-only tags and ignores timezone
4709
- information if present. Only one B<-d> option may be used per command.
4905
+ information if present. Only one B<-d> option may be used per command.
4710
4906
  Requires POSIX::strptime or Time::Piece for the inversion conversion when
4711
4907
  writing.
4712
4908
 
@@ -4775,7 +4971,7 @@ B<-htmlDump0> for absolute offsets. Currently only EXIF/TIFF and JPEG
4775
4971
  information is dumped, but the -u option can be used to give a raw hex dump
4776
4972
  of other file formats.
4777
4973
 
4778
- =item B<-j>[=I<JSONFILE>] (B<-json>)
4974
+ =item B<-j>[[+]=I<JSONFILE>] (B<-json>)
4779
4975
 
4780
4976
  Use JSON (JavaScript Object Notation) formatting for console output, or
4781
4977
  import JSON file if I<JSONFILE> is specified. This option may be combined
@@ -4786,15 +4982,16 @@ into individual tags in the JSON output, but the original structure may be
4786
4982
  preserved with the B<-struct> option (this also causes all list-type XMP
4787
4983
  tags to be output as JSON arrays, otherwise single-item lists would be
4788
4984
  output as simple strings). The B<-a> option is implied if the B<-g> or
4789
- B<-G> options are used, otherwise it is ignored and duplicate tags are
4790
- suppressed. Adding the B<-D> or B<-H> option changes tag values to JSON
4791
- objects with "val" and "id" fields, and adding B<-l> adds a "desc" field,
4792
- and a "num" field if the numerical value is different from the converted
4793
- "val". The B<-b> option may be added to output binary data, encoded in
4794
- base64 if necessary (indicated by "base64:" as the first 7 bytes of the
4795
- value), and B<-t> may be added to include tag table information (see B<-t>
4796
- for details). The JSON output is UTF-8 regardless of any B<-L> or
4797
- B<-charset> option setting, but the UTF-8 validation is disabled if a
4985
+ B<-G> options are used, otherwise it is ignored and tags with identical
4986
+ JSON names are suppressed. (B<-g4> may be used to ensure that all tags have
4987
+ unique JSON names.) Adding the B<-D> or B<-H> option changes tag values to
4988
+ JSON objects with "val" and "id" fields, and adding B<-l> adds a "desc"
4989
+ field, and a "num" field if the numerical value is different from the
4990
+ converted "val". The B<-b> option may be added to output binary data,
4991
+ encoded in base64 if necessary (indicated by ASCII "base64:" as the first 7
4992
+ bytes of the value), and B<-t> may be added to include tag table information
4993
+ (see B<-t> for details). The JSON output is UTF-8 regardless of any B<-L>
4994
+ or B<-charset> option setting, but the UTF-8 validation is disabled if a
4798
4995
  character set other than UTF-8 is specified.
4799
4996
 
4800
4997
  If I<JSONFILE> is specified, the file is imported and the tag definitions
@@ -4887,20 +5084,25 @@ when writing. For example, the following commands all have the same effect:
4887
5084
 
4888
5085
  =item B<-p> I<FMTFILE> or I<STR> (B<-printFormat>)
4889
5086
 
4890
- Print output in the format specified by the given file or string. Tag names
4891
- in the format file or string begin with a C<$> symbol and may contain a
4892
- leading group names and/or a trailing C<#>. Case is not significant.
4893
- Braces C<{}> may be used around the tag name to separate it from subsequent
4894
- text. Use C<$$> to represent a C<$> symbol, and C<$/> for a newline.
4895
- Multiple B<-p> options may be used, each contributing a line of text to the
4896
- output. Lines beginning with C<#[HEAD]> and C<#[TAIL]> are output before
4897
- the first processed file and after the last processed file respectively.
4898
- Lines beginning with C<#[SECT]> and C<#[ENDS]> are output around each
4899
- section of files. A section is defined as a group of consecutive files with
4900
- the same section header (eg. files are grouped by directory if C<#[SECT]>
4901
- contains C<$directory>). Lines beginning with C<#[BODY]> and lines not
4902
- beginning with C<#> are output for each processed file. Other lines
4903
- beginning with C<#> are ignored. For example, this format file:
5087
+ Print output in the format specified by the given file or string. The
5088
+ argument is interpreted as a string unless a file of that name exists, in
5089
+ which case the string is loaded from the contents of the file. Tag names in
5090
+ the format file or string begin with a C<$> symbol and may contain a leading
5091
+ group names and/or a trailing C<#>. Case is not significant. Braces C<{}>
5092
+ may be used around the tag name to separate it from subsequent text. Use
5093
+ C<$$> to represent a C<$> symbol, and C<$/> for a newline.
5094
+
5095
+ Multiple B<-p> options may be used, each contributing a line (or more) of
5096
+ text to the output. Lines beginning with C<#[HEAD]> and C<#[TAIL]> are
5097
+ output before the first processed file and after the last processed file
5098
+ respectively. Lines beginning with C<#[SECT]> and C<#[ENDS]> are output
5099
+ around each section of files. A section is defined as a group of
5100
+ consecutive files with the same section header (eg. files are grouped by
5101
+ directory if C<#[SECT]> contains C<$directory>). Lines beginning with
5102
+ C<#[BODY]> and lines not beginning with C<#> are output for each processed
5103
+ file. Lines beginning with C<#[IF]> are not output, but all BODY lines are
5104
+ skipped if any tag on an IF line doesn't exist. Other lines beginning with
5105
+ C<#> are ignored. For example, this format file:
4904
5106
 
4905
5107
  # this is a comment line
4906
5108
  #[HEAD]-- Generated by ExifTool $exifToolVersion --
@@ -4914,7 +5116,7 @@ with this command:
4914
5116
 
4915
5117
  produces output like this:
4916
5118
 
4917
- -- Generated by ExifTool 10.65 --
5119
+ -- Generated by ExifTool 11.41 --
4918
5120
  File: a.jpg - 2003:10:31 15:44:19
4919
5121
  (f/5.6, 1/60s, ISO 100)
4920
5122
  File: b.jpg - 2006:05:23 11:57:38
@@ -4932,7 +5134,8 @@ If a specified tag does not exist, a minor warning is issued and the line
4932
5134
  with the missing tag is not printed. However, the B<-f> option may be used
4933
5135
  to set the value of missing tags to '-' (but this may be configured via the
4934
5136
  MissingTagValue API option), or the B<-m> option may be used to ignore minor
4935
- warnings and leave the missing values empty.
5137
+ warnings and leave the missing values empty. Alternatively, B<-q -q> may be
5138
+ used to simply suppress the warning messages.
4936
5139
 
4937
5140
  The L</Advanced formatting feature> may be used to modify the values of
4938
5141
  individual tags with the B<-p> option.
@@ -4980,6 +5183,13 @@ Note that an empty separator ("") is allowed, and will join items with no
4980
5183
  separator when reading, or split the value into individual characters when
4981
5184
  writing.
4982
5185
 
5186
+ For pure binary output (B<-b> used without B<-j>, B<-php> or B<-X>), the
5187
+ first B<-sep> option specifies a list-item separator, and subsequent B<-sep>
5188
+ options specify a terminator added to the end of the list (or after each
5189
+ value if not a list). In these strings, C<\n>, C<\r> and C<\t> may be used
5190
+ to represent a newline, carriage return and tab respectively. By default,
5191
+ binary list items are separated by a newline, and no terminator is added.
5192
+
4983
5193
  =item B<-sort>, B<--sort>
4984
5194
 
4985
5195
  Sort output by tag description, or by tag name if the B<-s> option is used.
@@ -5009,8 +5219,8 @@ Output a tab-delimited list of description/values (useful for database
5009
5219
  import). May be combined with B<-s> to print tag names instead of
5010
5220
  descriptions, or B<-S> to print tag values only, tab-delimited on a single
5011
5221
  line. The B<-t> option may be combined with B<-j>, B<-php> or B<-X> to add
5012
- tag table information (table C<name>, decimal tag C<id>, and C<index> for
5013
- cases where multiple conditional tags exist with the same ID).
5222
+ tag table information (C<table>, tag C<id>, and C<index> for cases where
5223
+ multiple conditional tags exist with the same ID).
5014
5224
 
5015
5225
  =item B<-T> (B<-table>)
5016
5226
 
@@ -5132,10 +5342,11 @@ A special feature allows the copy number to be incremented for each
5132
5342
  processed file by using %C (upper case) instead of %c. This allows a
5133
5343
  sequential number to be added to output file names, even if the names are
5134
5344
  different. For %C, a copy number of zero is not omitted as it is with %c.
5135
- The number before the decimal place gives the starting index, the number
5136
- after the decimal place gives the field width. The following examples show
5137
- the output filenames when used with the command
5138
- C<exiftool rose.jpg star.jpg jet.jpg ...>:
5345
+ A leading '-' causes the number to be reset at the start of each new
5346
+ directory, and '+' has no effect. The number before the decimal place gives
5347
+ the starting index, the number after the decimal place gives the field
5348
+ width. The following examples show the output filenames when used with the
5349
+ command C<exiftool rose.jpg star.jpg jet.jpg ...>:
5139
5350
 
5140
5351
  -w %C%f.txt # 0rose.txt, 1star.txt, 2jet.txt
5141
5352
  -w %f-%10C.txt # rose-10.txt, star-11.txt, jet-12.txt
@@ -5171,12 +5382,21 @@ codes in exactly the same way as with %f and %e.
5171
5382
  format codes. (For B<-w>, this would be a file extension.) This change
5172
5383
  allows a simple file name to be specified, which, when combined with the
5173
5384
  append feature, provides a method to write metadata from multiple source
5174
- files to a single output file without the need for shell redirection.
5385
+ files to a single output file without the need for shell redirection. For
5386
+ example, the following pairs of commands give the same result:
5387
+
5388
+ # overwriting existing text file
5389
+ exiftool test.jpg > out.txt # shell redirection
5390
+ exiftool test.jpg -W+! out.txt # equivalent -W option
5175
5391
 
5176
- 4) Adding the B<-v> option to B<-W> generates a list of the tags and output
5177
- file names instead of giving a verbose dump of the entire file. (Unless
5178
- appending all output to one file for each source file by using B<-W+> with
5179
- an output file I<FMT> that does not contain %t, $g or %s.)
5392
+ # append to existing text file
5393
+ exiftool test.jpg >> out.txt # shell redirection
5394
+ exiftool test.jpg -W+ out.txt # equivalent -W option
5395
+
5396
+ 4) Adding the B<-v> option to B<-W> sends a list of the tags and output file
5397
+ names to the console instead of giving a verbose dump of the entire file.
5398
+ (Unless appending all output to one file for each source file by using
5399
+ B<-W+> with an output file I<FMT> that does not contain %t, $g or %s.)
5180
5400
 
5181
5401
  5) Individual list items are stored in separate files when B<-W> is combined
5182
5402
  with B<-b>, but note that for separate files to be created %c or %C must be
@@ -5244,7 +5464,14 @@ identify the originating document for extracted information. Embedded
5244
5464
  documents containing sub-documents are indicated with dashes in the family 3
5245
5465
  group name. (eg. C<Doc2-3> is the 3rd sub-document of the 2nd embedded
5246
5466
  document.) Note that this option may increase processing time substantially,
5247
- especially for PDF files with many embedded images.
5467
+ especially for PDF files with many embedded images or videos with streaming
5468
+ metadata.
5469
+
5470
+ When used with B<-ee>, the B<-p> option is evaluated for each embedded
5471
+ document as if it were a separate input file. This allows, for example,
5472
+ generation of GPS track logs from timed metadata in videos. See
5473
+ L<http://owl.phy.queensu.ca/~phil/exiftool/geotag.html#Inverse> for
5474
+ examples.
5248
5475
 
5249
5476
  =item B<-ext>[+] I<EXT>, B<--ext> I<EXT> (B<-extension>)
5250
5477
 
@@ -5267,6 +5494,9 @@ command line: 1) It applies to files in subdirectories when combined with
5267
5494
  the B<-r> option. 2) The B<-ext> option is case-insensitive, which is
5268
5495
  useful when processing files on case-sensitive filesystems.
5269
5496
 
5497
+ Note that all files specified on the command line will be processed
5498
+ regardless of extension unless the B<-ext> option is used.
5499
+
5270
5500
  =item B<-F>[I<OFFSET>] (B<-fixBase>)
5271
5501
 
5272
5502
  Fix the base for maker notes offsets. A common problem with some image
@@ -5290,9 +5520,11 @@ WAV/AVI files to search for additional metadata. These speed benefits are
5290
5520
  small when reading images directly from disk, but can be substantial if
5291
5521
  piping images through a network connection. For more substantial speed
5292
5522
  benefits, B<-fast2> also causes exiftool to avoid extracting any EXIF
5293
- MakerNote information. B<-fast3> avoids processing the file entirely, and
5294
- returns only an initial guess at FileType and the pseudo System tags. Has
5295
- no effect when writing.
5523
+ MakerNote information. B<-fast3> avoids extracting metadata from the file,
5524
+ and returns only pseudo System tags, but still reads the file header to
5525
+ obtain an educated guess at FileType. B<-fast4> doesn't even read the file
5526
+ header, and determines FileType based only on the file extension. Has no
5527
+ effect when writing.
5296
5528
 
5297
5529
  =item B<-fileOrder> [-]I<TAG>
5298
5530
 
@@ -5319,7 +5551,7 @@ more than one directory name. A special I<DIR> value of C<SYMLINKS> (case
5319
5551
  sensitive) may be specified to ignore symbolic links when the B<-r> option
5320
5552
  is used.
5321
5553
 
5322
- =item B<-if> I<EXPR>
5554
+ =item B<-if>[I<NUM>] I<EXPR>
5323
5555
 
5324
5556
  Specify a condition to be evaluated before processing each I<FILE>. I<EXPR>
5325
5557
  is a Perl-like logic expression containing tag names prefixed by C<$>
@@ -5331,7 +5563,7 @@ trailing C<#> character to disable print conversion. The expression
5331
5563
  C<$GROUP:all> evaluates to 1 if any tag exists in the specified C<GROUP>, or
5332
5564
  0 otherwise (see note 2 below). When multiple B<-if> options are used, all
5333
5565
  conditions must be satisfied to process the file. Returns an exit status of
5334
- 1 if all files fail the condition. Below are a few examples:
5566
+ 2 if all files fail the condition. Below are a few examples:
5335
5567
 
5336
5568
  # extract shutterspeed from all Canon images in a directory
5337
5569
  exiftool -shutterspeed -if '$make eq "Canon"' dir
@@ -5345,6 +5577,13 @@ conditions must be satisfied to process the file. Returns an exit status of
5345
5577
  # find images containing a specific keyword (case insensitive)
5346
5578
  exiftool -if '$keywords =~ /harvey/i' -filename dir
5347
5579
 
5580
+ Adding I<NUM> to the B<-if> option causes a separate processing pass to be
5581
+ executed for evaluating I<EXPR> at a B<-fast> level given by I<NUM> (see the
5582
+ B<-fast> option documentation for details). Without I<NUM>, only one
5583
+ processing pass is done at the level specified by the B<-fast> option. For
5584
+ example, using B<-if4> is possible if I<EXPR> uses only pseudo System tags,
5585
+ and may significantly speed processing if enough files fail the condition.
5586
+
5348
5587
  Notes:
5349
5588
 
5350
5589
  1) The B<-n> and B<-b> options also apply to tags used in I<EXPR>.
@@ -5372,6 +5611,10 @@ the associated NEF:
5372
5611
  the values of duplicate tags are accessible only by specifying a group name
5373
5612
  (such as a family 4 instance number, eg. C<$Copy1:TAG>, C<$Copy2:TAG>, etc).
5374
5613
 
5614
+ 6) A special "OK" UserParam is available to test the success of the previous
5615
+ command when B<-execute> was used, and may be used like any other tag in the
5616
+ condition (ie. "$OK").
5617
+
5375
5618
  =item B<-m> (B<-ignoreMinorErrors>)
5376
5619
 
5377
5620
  Ignore minor errors and warnings. This enables writing to files with minor
@@ -5379,9 +5622,11 @@ errors and disables some validation checks which could result in minor
5379
5622
  warnings. Generally, minor errors/warnings indicate a problem which usually
5380
5623
  won't result in loss of metadata if ignored. However, there are exceptions,
5381
5624
  so ExifTool leaves it up to you to make the final decision. Minor errors
5382
- and warnings are indicated by "[minor]" at the start of the message.
5625
+ and warnings are indicated by "[minor]" at the start of the message.
5383
5626
  Warnings which affect processing when ignored are indicated by "[Minor]"
5384
- (with a capital "M").
5627
+ (with a capital "M"). Note that this causes missing values in
5628
+ B<-tagsFromFile>, B<-p> and B<-if> strings to be set to an empty string
5629
+ rather than an undefined value.
5385
5630
 
5386
5631
  =item B<-o> I<OUTFILE> or I<FMT> (B<-out>)
5387
5632
 
@@ -5460,22 +5705,23 @@ required.
5460
5705
 
5461
5706
  =item B<-progress>[:[I<TITLE>]]
5462
5707
 
5463
- Show the progress when processing files. The progress count appears in
5464
- brackets after the name of each processed file, and gives the current file
5465
- number and the total number of files to be processed. Implies the B<-v0>
5466
- option if I<TITLE> is not used, printing the name of each processed file
5467
- when writing. When combined with the B<-if> option, the total count
5468
- includes all files before the condition is applied, but files that fail the
5469
- condition will not have their names printed.
5708
+ Show the progress when processing files. Without a colon, the B<-progress>
5709
+ option adds a progress count in brackets after the name of each processed
5710
+ file, giving the current file number and the total number of files to be
5711
+ processed. Implies the B<-v0> option, causing the names of processed files
5712
+ to also be printed when writing. When combined with the B<-if> option, the
5713
+ total count includes all files before the condition is applied, but files
5714
+ that fail the condition will not have their names printed.
5470
5715
 
5471
5716
  If followed by a colon (ie. B<-progress:>), the console window title is set
5472
5717
  according to the specified I<TITLE> string. If no I<TITLE> is given, a
5473
5718
  default I<TITLE> string of "ExifTool %p%%" is assumed. In the string, %f
5474
5719
  represents the file name, %p is the progress as a percent, %r is the
5475
- progress as a ratio, %[##]b is a progress bar of width ## (default 20), and
5476
- %% is a % character. May be combined with the normal B<-progress> option to
5477
- also show the progress count in console messages. (Note: For this feature
5478
- to function correctly on Mac/Linux, stderr must go to the console.)
5720
+ progress as a ratio, %##b is a progress bar of width "##" (20 characters if
5721
+ "##" is omitted), and %% is a % character. May be combined with the normal
5722
+ B<-progress> option to also show the progress count in console messages.
5723
+ (Note: For this feature to function correctly on Mac/Linux, stderr must go
5724
+ to the console.)
5479
5725
 
5480
5726
  =item B<-q> (B<-quiet>)
5481
5727
 
@@ -5490,8 +5736,9 @@ Recursively process files in subdirectories. Only meaningful if I<FILE> is
5490
5736
  a directory name. Subdirectories with names beginning with "." are not
5491
5737
  processed unless "." is added to the option name (ie. B<-r.> or
5492
5738
  B<-recurse.>). By default, exiftool will also follow symbolic links to
5493
- directories if supported by the system, but this may be disabled with C<-i
5494
- SYMLINKS> (see the B<-i> option for details).
5739
+ directories if supported by the system, but this may be disabled with
5740
+ C<-i SYMLINKS> (see the B<-i> option for details). Combine this with
5741
+ B<-ext> options to control the types of files processed.
5495
5742
 
5496
5743
  =item B<-scanForXMP>
5497
5744
 
@@ -5516,8 +5763,7 @@ binary data blocks. This is the same as two B<-u> options.
5516
5763
  =item B<-wm> I<MODE> (B<-writeMode>)
5517
5764
 
5518
5765
  Set mode for writing/creating tags. I<MODE> is a string of one or more
5519
- characters from the list below. Write mode is C<wcg> unless otherwise
5520
- specified.
5766
+ characters from the list below. The default write mode is C<wcg>.
5521
5767
 
5522
5768
  w - Write existing tags
5523
5769
  c - Create new tags
@@ -5533,11 +5779,12 @@ for EXIF this is the individual IFD (the family 1 group).
5533
5779
  =item B<-z> (B<-zip>)
5534
5780
 
5535
5781
  When reading, causes information to be extracted from .gz and .bz2
5536
- compressed images. (Only one image per archive. Requires gzip and bzip2 to
5537
- be installed on the system.) When writing, causes compressed information to
5538
- be written if supported by the metadata format. (eg. PNG supports
5539
- compressed textual metadata.) This option also disables the recommended
5540
- padding in embedded XMP, saving 2424 bytes when writing XMP in a file.
5782
+ compressed images (only one image per archive; requires gzip and bzip2 to be
5783
+ available). When writing, causes compressed information to be written if
5784
+ supported by the metadata format (eg. compressed textual metadata in PNG),
5785
+ disables the recommended padding in embedded XMP (saving 2424 bytes when
5786
+ writing XMP in a file), and writes XMP in shorthand format -- the equivalent
5787
+ of setting the API Compress, Compact and XMPShorthand options to 1.
5541
5788
 
5542
5789
  =back
5543
5790
 
@@ -5550,12 +5797,14 @@ padding in embedded XMP, saving 2424 bytes when writing XMP in a file.
5550
5797
  Read command-line arguments from the specified file. The file contains one
5551
5798
  argument per line (NOT one option per line -- some options require
5552
5799
  additional arguments, and all arguments must be placed on separate lines).
5553
- Blank lines and lines beginning with C<#> are ignored. White space at the
5554
- start of a line is removed. Normal shell processing of arguments is not
5555
- performed, which among other things means that arguments should not be
5556
- quoted and spaces are treated as any other character. I<ARGFILE> may exist
5557
- relative to either the current directory or the exiftool directory unless an
5558
- absolute pathname is given.
5800
+ Blank lines and lines beginning with C<#> are ignored (unless they start
5801
+ with C<#[CSTR]>, in which case the rest of the line is treated as a C
5802
+ string, allowing standard C escape sequences such as "\n" for a newline).
5803
+ White space at the start of a line is removed. Normal shell processing of
5804
+ arguments is not performed, which among other things means that arguments
5805
+ should not be quoted and spaces are treated as any other character.
5806
+ I<ARGFILE> may exist relative to either the current directory or the
5807
+ exiftool directory unless an absolute pathname is given.
5559
5808
 
5560
5809
  For example, the following I<ARGFILE> will set the value of Copyright to
5561
5810
  "Copyright YYYY, Phil Harvey", where "YYYY" is the year of CreateDate:
@@ -5754,12 +6003,11 @@ load exiftool for each invocation.
5754
6003
 
5755
6004
  =over 5
5756
6005
 
5757
- =item B<-api> I<OPT[=VAL]>
6006
+ =item B<-api> I<OPT[[^]=[VAL]]>
5758
6007
 
5759
6008
  Set ExifTool API option. I<OPT> is an API option name. The option value is
5760
- set to 1 if I<=VAL> is omitted, or undef if just I<VAL> is omitted. An
5761
- option may not be set to an empty string ("") via the command line, but the
5762
- config file may be used to accomplish this if necessary. See
6009
+ set to 1 if I<=VAL> is omitted. If I<VAL> is omitted, the option value is
6010
+ set to undef if C<=> is used, or an empty string with C<^=>. See
5763
6011
  L<Image::ExifTool Options|Image::ExifTool/Options> for a list of available
5764
6012
  API options. This overrides API options set via the config file.
5765
6013
 
@@ -5775,12 +6023,13 @@ options on the command line.
5775
6023
 
5776
6024
  Load specified configuration file instead of the default ".ExifTool_config".
5777
6025
  If used, this option must come before all other arguments on the command
5778
- line and applies to all B<-execute>'d commands. The I<CFGFILE> name may
5779
- contain a directory specification (otherwise the file must exist in the
5780
- current directory), or may be set to an empty string ("") to disable loading
5781
- of the config file. See the sample configuration file and "config.html" in
5782
- the full ExifTool distribution for more information about the ExifTool
5783
- configuration file.
6026
+ line and applies to all B<-execute>'d commands. The I<CFGFILE> must exist
6027
+ relative to the current working directory or the exiftool application
6028
+ directory unless an absolute path is specified. Loading of the default
6029
+ config file may be disabled by setting I<CFGFILE> to an empty string (ie.
6030
+ ""). See L<http://owl.phy.queensu.ca/~phil/exiftool/config.html> and
6031
+ config_files/example.config in the full ExifTool distribution for details
6032
+ about the configuration file syntax.
5784
6033
 
5785
6034
  =item B<-echo>[I<NUM>] I<TEXT>
5786
6035
 
@@ -5868,7 +6117,7 @@ process immediately after writing C<-execute\n>. (There is no associated
5868
6117
  delay when writing arguments via a pipe with C<-@ ->, so the signal is not
5869
6118
  necessary when using this technique.)
5870
6119
 
5871
- =item B<-userParam> I<PARAM[=VAL]>
6120
+ =item B<-userParam> I<PARAM[[^]=[VAL]]>
5872
6121
 
5873
6122
  Set user parameter. I<PARAM> is an arbitrary user parameter name. This
5874
6123
  is an interface to the API UserParam option (see the
@@ -5877,7 +6126,8 @@ provides a method to access user-defined parameters from inside tag name
5877
6126
  expressions (as if it were any other tag, see example below), and from
5878
6127
  PrintConv/ValueConv logic (via the ExifTool Options function). Similar to
5879
6128
  the B<-api> option, the parameter value is set to 1 if I<=VAL> is omitted,
5880
- or undef if just I<VAL> is omitted.
6129
+ undef if just I<VAL> is omitted with C<=>, or an empty string if
6130
+ I<VAL> is omitted with C<^=>.
5881
6131
 
5882
6132
  exiftool -p '$test from $filename' -userparam test=Hello FILE
5883
6133
 
@@ -5901,23 +6151,46 @@ underlines replaced by a single underline:
5901
6151
 
5902
6152
  exiftool -p '${make;tr/ /_/;s/__+/_/g}' image.jpg
5903
6153
 
6154
+ An C<@> may be added after the tag name to make the expression act on
6155
+ individual list items for list-type tags, simplifying list processing. Set
6156
+ C<$_> to undef to remove an item from the list. As an example, the
6157
+ following command returns all subjects not containing the string "xxx":
6158
+
6159
+ exiftool -p '${subject@;$_=undef if /xxx/}' image.jpg
6160
+
5904
6161
  A default expression of C<tr(/\\?*:|"E<lt>E<gt>\0)()d> is assumed if the
5905
6162
  expression is empty (ie. C<${TAG;}>). This removes the characters / \ ? * :
5906
6163
  | E<lt> E<gt> and null from the printed value. (These characters are
5907
6164
  illegal in Windows file names, so this feature is useful if tag values are
5908
6165
  used in file names.)
5909
6166
 
5910
- ExifTool provides a C<DateFmt> utility to simplify reformatting of
5911
- individual date/time values. The function acts on a standard EXIF-formatted
5912
- date/time value in C<$_> and formats it according to the specified format
5913
- string (see the B<-d> option). For example:
6167
+ =head4 Helper functions
6168
+
6169
+ C<DateFmt>
6170
+
6171
+ Simplifies reformatting of individual date/time values. This function acts
6172
+ on a standard EXIF-formatted date/time value in C<$_> and formats it
6173
+ according to the specified format string (see the B<-d> option). To avoid
6174
+ trying to reformat an already-formatted date/time value, a C<#> must be
6175
+ added to the tag name (as in the example below) if the B<-d> option is also
6176
+ used. For example:
5914
6177
 
5915
6178
  exiftool -p '${createdate#;DateFmt("%Y-%m-%d_%H%M%S")}' a.jpg
5916
6179
 
5917
- A C<NoDups> utility is also provided to remove duplicate items from a list
5918
- with a separator specified by the B<-sep> option. This function is most
5919
- useful when copying list-type tags. For example, the following command may
5920
- be used to remove duplicate Keywords:
6180
+ C<ShiftTime>
6181
+
6182
+ Shifts EXIF-formatted date/time string by a specified amount. Start with a
6183
+ leading minus sign to shift backwards in time. See
6184
+ L<Image::ExifTool::Shift.pl|Image::ExifTool::Shift.pl> for details about
6185
+ shift syntax. For example, to shift a date/time value back by one year:
6186
+
6187
+ exiftool -p '${createdate;ShiftTime("-1:0:0 0")}' a.jpg
6188
+
6189
+ C<NoDups>
6190
+
6191
+ Removes duplicate items from a list with a separator specified by the
6192
+ B<-sep> option. This function is most useful when copying list-type tags.
6193
+ For example, the following command may be used to remove duplicate Keywords:
5921
6194
 
5922
6195
  exiftool -sep '##' '-keywords<${keywords;NoDups}' a.jpg
5923
6196
 
@@ -5944,10 +6217,11 @@ ExifTool 9.79 and later allow the file name encoding to be specified with
5944
6217
  C<-charset filename=CHARSET>, where C<CHARSET> is the name of a valid
5945
6218
  ExifTool character set, preferably C<UTF8> (see the B<-charset> option for a
5946
6219
  complete list). Setting this triggers the use of Windows wide-character i/o
5947
- routines, thus providing support for all Unicode file names. But note that
5948
- it is not trivial to pass properly encoded file names on the Windows command
5949
- line (see L<http://owl.phy.queensu.ca/~phil/exiftool/faq.html#Q18> for
5950
- details), so placing them in a UTF-8 encoded B<-@> argfile and using
6220
+ routines, thus providing support for most Unicode file names (see note 4).
6221
+ But note that it is not trivial to pass properly encoded file names on the
6222
+ Windows command line (see
6223
+ L<http://owl.phy.queensu.ca/~phil/exiftool/faq.html#Q18> for details), so
6224
+ placing them in a UTF-8 encoded B<-@> argfile and using
5951
6225
  C<-charset filename=utf8> is recommended if possible.
5952
6226
 
5953
6227
  A warning is issued if a specified filename contains special characters and
@@ -5980,6 +6254,9 @@ like Cygwin.
5980
6254
  3) See L</WRITING READ-ONLY FILES> below for a note about editing read-only
5981
6255
  files with Unicode names.
5982
6256
 
6257
+ 4) Unicode file names with surrogate pairs (code points over U+FFFF) still
6258
+ cause problems.
6259
+
5983
6260
  =head1 WRITING READ-ONLY FILES
5984
6261
 
5985
6262
  In general, ExifTool may be used to write metadata to read-only files
@@ -6008,7 +6285,11 @@ arguments containing special characters.
6008
6285
  =item exiftool -a -u -g1 a.jpg
6009
6286
 
6010
6287
  Print all meta information in an image, including duplicate and unknown
6011
- tags, sorted by group (for family 1).
6288
+ tags, sorted by group (for family 1). For performance reasons, this command
6289
+ may not extract all available metadata. (Metadata in embedded documents,
6290
+ metadata extracted by external utilities, and metadata requiring excessive
6291
+ processing time may not be extracted). Add C<-ee> and C<-api RequestAll=3>
6292
+ to the command to extract absolutely everything available.
6012
6293
 
6013
6294
  =item exiftool -common dir
6014
6295
 
@@ -6362,10 +6643,9 @@ the image (with the inverse command) later in a workflow.
6362
6643
  This command performs exactly the same task as the command above, except
6363
6644
  that the B<-o> option will not write to an output file that already exists.
6364
6645
 
6365
- =item exiftool -if '$jpgfromraw' -b -jpgfromraw -w %d%f_%ue.jpg -execute
6366
- -if '$previewimage' -b -previewimage -w %d%f_%ue.jpg -execute
6367
- -tagsfromfile @ -srcfile %d%f_%ue.jpg -overwrite_original
6368
- -common_args --ext jpg DIR
6646
+ =item exiftool -b -jpgfromraw -w %d%f_%ue.jpg -execute -b -previewimage -w
6647
+ %d%f_%ue.jpg -execute -tagsfromfile @ -srcfile %d%f_%ue.jpg
6648
+ -overwrite_original -common_args --ext jpg DIR
6369
6649
 
6370
6650
  [Advanced] Extract JpgFromRaw or PreviewImage from all but JPG files in DIR,
6371
6651
  saving them with file names like C<image_EXT.jpg>, then add all meta
@@ -6554,12 +6834,12 @@ flexibility of ExifTool.)
6554
6834
  =head1 EXIT STATUS
6555
6835
 
6556
6836
  The exiftool application exits with a status of 0 on success, or 1 if an
6557
- error occurred or if all files failed the B<-if> condition (for any of the
6558
- commands if B<-execute> was used).
6837
+ error occurred, or 2 if all files failed the B<-if> condition (for any of
6838
+ the commands if B<-execute> was used).
6559
6839
 
6560
6840
  =head1 AUTHOR
6561
6841
 
6562
- Copyright 2003-2017, Phil Harvey
6842
+ Copyright 2003-2019, Phil Harvey
6563
6843
 
6564
6844
  This is free software; you can redistribute it and/or modify it under the
6565
6845
  same terms as Perl itself.