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.
- checksums.yaml +4 -4
- data/bin/Changes +818 -19
- data/bin/MANIFEST +38 -0
- data/bin/META.json +1 -1
- data/bin/META.yml +1 -1
- data/bin/README +48 -44
- data/bin/arg_files/exif2xmp.args +4 -1
- data/bin/arg_files/gps2xmp.args +4 -1
- data/bin/arg_files/iptcCore.args +8 -0
- data/bin/arg_files/xmp2exif.args +4 -1
- data/bin/arg_files/xmp2gps.args +4 -1
- data/bin/config_files/dji.config +131 -0
- data/bin/config_files/example.config +6 -2
- data/bin/config_files/gps2utm.config +256 -256
- data/bin/config_files/nksc.config +146 -0
- data/bin/config_files/picasa_faces.config +382 -382
- data/bin/exiftool +688 -408
- data/bin/fmt_files/gpx.fmt +10 -6
- data/bin/fmt_files/gpx_wpt.fmt +10 -6
- data/bin/fmt_files/kml.fmt +8 -5
- data/bin/lib/File/RandomAccess.pm +48 -8
- data/bin/lib/File/RandomAccess.pod +21 -2
- data/bin/lib/Image/ExifTool.pm +645 -256
- data/bin/lib/Image/ExifTool.pod +219 -164
- data/bin/lib/Image/ExifTool/AES.pm +1 -1
- data/bin/lib/Image/ExifTool/AFCP.pm +3 -8
- data/bin/lib/Image/ExifTool/AIFF.pm +12 -4
- data/bin/lib/Image/ExifTool/APE.pm +1 -1
- data/bin/lib/Image/ExifTool/APP12.pm +1 -1
- data/bin/lib/Image/ExifTool/ASF.pm +19 -6
- data/bin/lib/Image/ExifTool/Apple.pm +13 -5
- data/bin/lib/Image/ExifTool/Audible.pm +1 -1
- data/bin/lib/Image/ExifTool/BMP.pm +1 -1
- data/bin/lib/Image/ExifTool/BPG.pm +17 -15
- data/bin/lib/Image/ExifTool/BZZ.pm +1 -1
- data/bin/lib/Image/ExifTool/BigTIFF.pm +30 -15
- data/bin/lib/Image/ExifTool/BuildTagLookup.pm +103 -52
- data/bin/lib/Image/ExifTool/Canon.pm +684 -112
- data/bin/lib/Image/ExifTool/CanonCustom.pm +119 -9
- data/bin/lib/Image/ExifTool/CanonRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/CanonVRD.pm +13 -26
- data/bin/lib/Image/ExifTool/CaptureOne.pm +1 -1
- data/bin/lib/Image/ExifTool/Casio.pm +1 -1
- data/bin/lib/Image/ExifTool/Charset.pm +1 -1
- data/bin/lib/Image/ExifTool/DICOM.pm +12 -5
- data/bin/lib/Image/ExifTool/DJI.pm +51 -3
- data/bin/lib/Image/ExifTool/DNG.pm +15 -8
- data/bin/lib/Image/ExifTool/DPX.pm +1 -1
- data/bin/lib/Image/ExifTool/DV.pm +1 -1
- data/bin/lib/Image/ExifTool/DarwinCore.pm +63 -23
- data/bin/lib/Image/ExifTool/DjVu.pm +4 -2
- data/bin/lib/Image/ExifTool/EXE.pm +30 -6
- data/bin/lib/Image/ExifTool/Exif.pm +351 -109
- data/bin/lib/Image/ExifTool/FITS.pm +148 -0
- data/bin/lib/Image/ExifTool/FLAC.pm +2 -2
- data/bin/lib/Image/ExifTool/FLIF.pm +1 -1
- data/bin/lib/Image/ExifTool/FLIR.pm +109 -13
- data/bin/lib/Image/ExifTool/Fixup.pm +1 -1
- data/bin/lib/Image/ExifTool/Flash.pm +3 -3
- data/bin/lib/Image/ExifTool/FlashPix.pm +433 -9
- data/bin/lib/Image/ExifTool/Font.pm +2 -2
- data/bin/lib/Image/ExifTool/FotoStation.pm +1 -1
- data/bin/lib/Image/ExifTool/FujiFilm.pm +336 -16
- data/bin/lib/Image/ExifTool/GE.pm +1 -1
- data/bin/lib/Image/ExifTool/GIF.pm +5 -7
- data/bin/lib/Image/ExifTool/GIMP.pm +39 -3
- data/bin/lib/Image/ExifTool/GPS.pm +48 -22
- data/bin/lib/Image/ExifTool/GeoTiff.pm +23 -23
- data/bin/lib/Image/ExifTool/Geotag.pm +80 -45
- data/bin/lib/Image/ExifTool/GoPro.pm +709 -0
- data/bin/lib/Image/ExifTool/H264.pm +40 -18
- data/bin/lib/Image/ExifTool/HP.pm +1 -1
- data/bin/lib/Image/ExifTool/HTML.pm +19 -12
- data/bin/lib/Image/ExifTool/HtmlDump.pm +37 -26
- data/bin/lib/Image/ExifTool/ICC_Profile.pm +297 -23
- data/bin/lib/Image/ExifTool/ID3.pm +12 -7
- data/bin/lib/Image/ExifTool/IPTC.pm +48 -19
- data/bin/lib/Image/ExifTool/ISO.pm +1 -1
- data/bin/lib/Image/ExifTool/ITC.pm +1 -1
- data/bin/lib/Image/ExifTool/Import.pm +13 -9
- data/bin/lib/Image/ExifTool/InDesign.pm +3 -5
- data/bin/lib/Image/ExifTool/JPEG.pm +22 -11
- data/bin/lib/Image/ExifTool/JPEGDigest.pm +1 -1
- data/bin/lib/Image/ExifTool/JSON.pm +3 -3
- data/bin/lib/Image/ExifTool/JVC.pm +1 -1
- data/bin/lib/Image/ExifTool/Jpeg2000.pm +2 -2
- data/bin/lib/Image/ExifTool/Kodak.pm +1233 -58
- data/bin/lib/Image/ExifTool/KyoceraRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/LNK.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/cs.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/de.pm +33 -24
- data/bin/lib/Image/ExifTool/Lang/en_ca.pm +64 -2
- data/bin/lib/Image/ExifTool/Lang/en_gb.pm +64 -2
- data/bin/lib/Image/ExifTool/Lang/es.pm +8 -4
- data/bin/lib/Image/ExifTool/Lang/fi.pm +46 -4
- data/bin/lib/Image/ExifTool/Lang/fr.pm +5 -3
- data/bin/lib/Image/ExifTool/Lang/it.pm +6 -3
- data/bin/lib/Image/ExifTool/Lang/ja.pm +15 -3
- data/bin/lib/Image/ExifTool/Lang/ko.pm +5 -2
- data/bin/lib/Image/ExifTool/Lang/nl.pm +6 -3
- data/bin/lib/Image/ExifTool/Lang/pl.pm +2 -2
- data/bin/lib/Image/ExifTool/Lang/ru.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/sv.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/tr.pm +4 -2
- data/bin/lib/Image/ExifTool/Lang/zh_cn.pm +1 -1
- data/bin/lib/Image/ExifTool/Lang/zh_tw.pm +1 -1
- data/bin/lib/Image/ExifTool/Leaf.pm +1 -1
- data/bin/lib/Image/ExifTool/Lytro.pm +4 -8
- data/bin/lib/Image/ExifTool/M2TS.pm +10 -9
- data/bin/lib/Image/ExifTool/MIE.pm +12 -8
- data/bin/lib/Image/ExifTool/MIEUnits.pod +1 -1
- data/bin/lib/Image/ExifTool/MIFF.pm +1 -1
- data/bin/lib/Image/ExifTool/MNG.pm +1 -1
- data/bin/lib/Image/ExifTool/MOI.pm +1 -1
- data/bin/lib/Image/ExifTool/MPC.pm +1 -1
- data/bin/lib/Image/ExifTool/MPEG.pm +2 -3
- data/bin/lib/Image/ExifTool/MPF.pm +6 -6
- data/bin/lib/Image/ExifTool/MWG.pm +4 -4
- data/bin/lib/Image/ExifTool/MXF.pm +2 -2
- data/bin/lib/Image/ExifTool/MacOS.pm +184 -34
- data/bin/lib/Image/ExifTool/MakerNotes.pm +101 -18
- data/bin/lib/Image/ExifTool/Matroska.pm +1 -1
- data/bin/lib/Image/ExifTool/Microsoft.pm +5 -3
- data/bin/lib/Image/ExifTool/Minolta.pm +89 -62
- data/bin/lib/Image/ExifTool/MinoltaRaw.pm +1 -1
- data/bin/lib/Image/ExifTool/Motorola.pm +1 -1
- data/bin/lib/Image/ExifTool/Nikon.pm +1511 -380
- data/bin/lib/Image/ExifTool/NikonCapture.pm +1 -1
- data/bin/lib/Image/ExifTool/NikonCustom.pm +2758 -2935
- data/bin/lib/Image/ExifTool/Nintendo.pm +1 -1
- data/bin/lib/Image/ExifTool/OOXML.pm +1 -1
- data/bin/lib/Image/ExifTool/Ogg.pm +1 -1
- data/bin/lib/Image/ExifTool/Olympus.pm +47 -8
- data/bin/lib/Image/ExifTool/OpenEXR.pm +1 -1
- data/bin/lib/Image/ExifTool/Opus.pm +1 -1
- data/bin/lib/Image/ExifTool/PCX.pm +138 -0
- data/bin/lib/Image/ExifTool/PDF.pm +58 -42
- data/bin/lib/Image/ExifTool/PGF.pm +1 -1
- data/bin/lib/Image/ExifTool/PICT.pm +1 -1
- data/bin/lib/Image/ExifTool/PLIST.pm +12 -5
- data/bin/lib/Image/ExifTool/PLUS.pm +1 -1
- data/bin/lib/Image/ExifTool/PNG.pm +108 -10
- data/bin/lib/Image/ExifTool/PPM.pm +3 -3
- data/bin/lib/Image/ExifTool/PSP.pm +1 -1
- data/bin/lib/Image/ExifTool/Palm.pm +1 -1
- data/bin/lib/Image/ExifTool/Panasonic.pm +299 -31
- data/bin/lib/Image/ExifTool/PanasonicRaw.pm +201 -19
- data/bin/lib/Image/ExifTool/Pentax.pm +164 -143
- data/bin/lib/Image/ExifTool/PhaseOne.pm +12 -5
- data/bin/lib/Image/ExifTool/PhotoCD.pm +9 -10
- data/bin/lib/Image/ExifTool/PhotoMechanic.pm +1 -1
- data/bin/lib/Image/ExifTool/Photoshop.pm +230 -60
- data/bin/lib/Image/ExifTool/PostScript.pm +29 -4
- data/bin/lib/Image/ExifTool/PrintIM.pm +1 -1
- data/bin/lib/Image/ExifTool/Qualcomm.pm +2 -2
- data/bin/lib/Image/ExifTool/QuickTime.pm +1539 -279
- data/bin/lib/Image/ExifTool/QuickTimeStream.pl +1857 -0
- data/bin/lib/Image/ExifTool/README +84 -46
- data/bin/lib/Image/ExifTool/RIFF.pm +116 -23
- data/bin/lib/Image/ExifTool/RSRC.pm +1 -1
- data/bin/lib/Image/ExifTool/RTF.pm +6 -4
- data/bin/lib/Image/ExifTool/Radiance.pm +1 -1
- data/bin/lib/Image/ExifTool/Rawzor.pm +3 -2
- data/bin/lib/Image/ExifTool/Real.pm +1 -1
- data/bin/lib/Image/ExifTool/Reconyx.pm +261 -7
- data/bin/lib/Image/ExifTool/Red.pm +325 -0
- data/bin/lib/Image/ExifTool/Ricoh.pm +3 -7
- data/bin/lib/Image/ExifTool/Samsung.pm +95 -25
- data/bin/lib/Image/ExifTool/Sanyo.pm +1 -1
- data/bin/lib/Image/ExifTool/Scalado.pm +1 -1
- data/bin/lib/Image/ExifTool/Shift.pl +26 -12
- data/bin/lib/Image/ExifTool/Shortcuts.pm +9 -2
- data/bin/lib/Image/ExifTool/Sigma.pm +36 -30
- data/bin/lib/Image/ExifTool/SigmaRaw.pm +3 -8
- data/bin/lib/Image/ExifTool/Sony.pm +531 -177
- data/bin/lib/Image/ExifTool/SonyIDC.pm +63 -3
- data/bin/lib/Image/ExifTool/Stim.pm +2 -2
- data/bin/lib/Image/ExifTool/TagInfoXML.pm +23 -23
- data/bin/lib/Image/ExifTool/TagLookup.pm +6352 -5062
- data/bin/lib/Image/ExifTool/TagNames.pod +3024 -565
- data/bin/lib/Image/ExifTool/Theora.pm +1 -1
- data/bin/lib/Image/ExifTool/Torrent.pm +2 -2
- data/bin/lib/Image/ExifTool/Unknown.pm +1 -1
- data/bin/lib/Image/ExifTool/VCard.pm +47 -9
- data/bin/lib/Image/ExifTool/Validate.pm +391 -99
- data/bin/lib/Image/ExifTool/Vorbis.pm +1 -1
- data/bin/lib/Image/ExifTool/WTV.pm +319 -0
- data/bin/lib/Image/ExifTool/WriteCanonRaw.pl +1 -1
- data/bin/lib/Image/ExifTool/WriteExif.pl +91 -18
- data/bin/lib/Image/ExifTool/WriteIPTC.pl +6 -6
- data/bin/lib/Image/ExifTool/WritePDF.pl +13 -12
- data/bin/lib/Image/ExifTool/WritePNG.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePhotoshop.pl +1 -1
- data/bin/lib/Image/ExifTool/WritePostScript.pl +2 -2
- data/bin/lib/Image/ExifTool/WriteQuickTime.pl +764 -121
- data/bin/lib/Image/ExifTool/WriteXMP.pl +176 -67
- data/bin/lib/Image/ExifTool/Writer.pl +490 -246
- data/bin/lib/Image/ExifTool/XMP.pm +216 -76
- data/bin/lib/Image/ExifTool/XMP2.pl +54 -10
- data/bin/lib/Image/ExifTool/XMPStruct.pl +14 -11
- data/bin/lib/Image/ExifTool/ZIP.pm +60 -15
- data/bin/lib/Image/ExifTool/iWork.pm +12 -5
- data/bin/perl-Image-ExifTool.spec +46 -44
- data/lib/exiftool_vendored/version.rb +1 -1
- 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 = '
|
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 $
|
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, $
|
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] =~
|
538
|
+
if (not @ARGV or $ARGV[0] =~ /^(-|\xe2\x88\x92)execute(\d*)$/i) {
|
514
539
|
if (@ARGV) {
|
515
|
-
$executeID = $
|
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
|
-
|
703
|
-
|
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
|
-
|
718
|
-
|
719
|
-
$
|
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
|
-
|
740
|
-
|
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 =
|
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 (
|
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
|
-
|
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 $
|
978
|
+
(/^L$/ or $a eq 'latin') and $mt->Options(Charset => 'Latin'), next;
|
945
979
|
if ($a eq 'lang') {
|
946
|
-
$langOpt = (@ARGV and $ARGV[0] !~
|
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
|
-
$
|
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(:.*)
|
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
|
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
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
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
|
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 ($
|
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
|
-
|
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 $
|
1750
|
-
printf($o "%5d hard links could not be created\n", $
|
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
|
-
|
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 $
|
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 (
|
1881
|
+
if (@condition) {
|
1819
1882
|
unless ($file eq '-' or $et->Exists($file)) {
|
1820
|
-
Warn "File not found
|
1883
|
+
Warn "Error: File not found - $file\n";
|
1821
1884
|
FileNotFound($file);
|
1822
1885
|
++$countBad;
|
1823
1886
|
return;
|
1824
1887
|
}
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
1828
|
-
|
1829
|
-
|
1830
|
-
|
1831
|
-
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1840
|
-
|
1841
|
-
|
1842
|
-
|
1843
|
-
|
1844
|
-
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
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
|
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
|
-
|
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
|
-
|
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, $_,
|
2011
|
-
|
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)
|
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
|
-
|
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
|
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
|
2687
|
-
|
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
|
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
|
-
|
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")
|
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, $
|
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 $
|
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, $
|
2869
|
-
Warn "Error renaming temporary file to $
|
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,
|
2914
|
-
|
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
|
-
|
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
|
-
|
3033
|
+
$countLink{BadSym} = ($countLink{BadSym} || 0) + 1;
|
2923
3034
|
}
|
2924
3035
|
}
|
2925
3036
|
if (defined $testName) {
|
2926
|
-
$testName = NextUnusedFilename($testName,
|
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)
|
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
|
-
($
|
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
|
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)
|
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 =
|
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
|
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
|
-
|
3388
|
-
|
3389
|
-
|
3390
|
-
|
3391
|
-
$
|
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)
|
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
|
-
|
3476
|
-
|
3477
|
-
|
3478
|
-
|
3479
|
-
|
3480
|
-
|
3481
|
-
|
3482
|
-
|
3483
|
-
|
3484
|
-
$
|
3485
|
-
|
3486
|
-
|
3487
|
-
|
3488
|
-
|
3489
|
-
|
3490
|
-
|
3491
|
-
|
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
|
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
|
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
|
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
|
-
|
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
|
3931
|
-
$arg
|
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
|
4059
|
-
-I<TAG>=[I<VALUE>]
|
4060
|
-
metadata, the B<-tagsFromFile> feature is used. By default
|
4061
|
-
files are preserved with C<_original> appended to their names
|
4062
|
-
verify that the new files are OK before erasing the originals.
|
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 |
|
4079
|
-
3G2 r/w |
|
4080
|
-
3GP r/w |
|
4081
|
-
A r |
|
4082
|
-
AA r |
|
4083
|
-
|
4084
|
-
|
4085
|
-
|
4086
|
-
|
4087
|
-
|
4088
|
-
|
4089
|
-
|
4090
|
-
|
4091
|
-
|
4092
|
-
|
4093
|
-
|
4094
|
-
|
4095
|
-
|
4096
|
-
|
4097
|
-
|
4098
|
-
|
4099
|
-
|
4100
|
-
|
4101
|
-
|
4102
|
-
|
4103
|
-
|
4104
|
-
|
4105
|
-
|
4106
|
-
|
4107
|
-
|
4108
|
-
|
4109
|
-
|
4110
|
-
|
4111
|
-
|
4112
|
-
|
4113
|
-
|
4114
|
-
|
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[
|
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]
|
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)
|
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
|
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]
|
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]
|
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>[
|
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<-
|
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,
|
4328
|
-
|
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>.
|
4435
|
-
|
4436
|
-
|
4437
|
-
|
4438
|
-
|
4439
|
-
|
4440
|
-
|
4441
|
-
|
4442
|
-
|
4443
|
-
|
4444
|
-
|
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.
|
4568
|
-
with the B<-b> option
|
4569
|
-
|
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
|
-
|
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
|
4603
|
-
|
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
|
4672
|
-
|
4673
|
-
|
4674
|
-
|
4675
|
-
|
4676
|
-
|
4677
|
-
|
4678
|
-
|
4679
|
-
|
4680
|
-
the
|
4681
|
-
|
4682
|
-
|
4683
|
-
|
4684
|
-
|
4685
|
-
|
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
|
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
|
4790
|
-
suppressed.
|
4791
|
-
|
4792
|
-
|
4793
|
-
"
|
4794
|
-
|
4795
|
-
|
4796
|
-
|
4797
|
-
B<-
|
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.
|
4891
|
-
|
4892
|
-
|
4893
|
-
|
4894
|
-
|
4895
|
-
|
4896
|
-
|
4897
|
-
|
4898
|
-
|
4899
|
-
|
4900
|
-
|
4901
|
-
|
4902
|
-
|
4903
|
-
|
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
|
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 (
|
5013
|
-
|
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
|
-
|
5136
|
-
|
5137
|
-
the
|
5138
|
-
|
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
|
-
|
5177
|
-
|
5178
|
-
|
5179
|
-
|
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
|
5294
|
-
returns only
|
5295
|
-
|
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
|
-
|
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.
|
5464
|
-
brackets after the name of each processed
|
5465
|
-
number and the total number of files to be
|
5466
|
-
|
5467
|
-
when writing. When combined with the B<-if> option, the
|
5468
|
-
includes all files before the condition is applied, but files
|
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,
|
5476
|
-
%% is a % character. May be combined with the normal
|
5477
|
-
also show the progress count in console messages.
|
5478
|
-
to function correctly on Mac/Linux, stderr must go
|
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
|
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.
|
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
|
5537
|
-
|
5538
|
-
|
5539
|
-
|
5540
|
-
|
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
|
5554
|
-
|
5555
|
-
|
5556
|
-
|
5557
|
-
|
5558
|
-
|
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
|
5761
|
-
|
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>
|
5779
|
-
|
5780
|
-
|
5781
|
-
|
5782
|
-
|
5783
|
-
|
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
|
-
|
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
|
-
|
5911
|
-
|
5912
|
-
|
5913
|
-
|
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
|
-
|
5918
|
-
|
5919
|
-
|
5920
|
-
|
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
|
5948
|
-
it is not trivial to pass properly encoded file names on the
|
5949
|
-
line (see
|
5950
|
-
details), so
|
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 -
|
6366
|
-
|
6367
|
-
-
|
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
|
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-
|
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.
|