UNPKG

@uswriting/exiftool

Version:

ExifTool powered by WebAssembly to extract and write metadata from files in browsers and Node.js environments using zeroperl

1 lines 132 kB
function be(n,r,e,t,i,$,o){try{var l=n[$](o),f=l.value}catch(s){e(s);return}l.done?r(f):Promise.resolve(f).then(t,i)}function U(n){return function(){var r=this,e=arguments;return new Promise(function(t,i){var $=n.apply(r,e);function o(f){be($,t,i,o,l,"next",f)}function l(f){be($,t,i,o,l,"throw",f)}o(void 0)})}}function W(n,r){return r!=null&&typeof Symbol!="undefined"&&r[Symbol.hasInstance]?!!r[Symbol.hasInstance](n):W(n,r)}function Se(n){if(Array.isArray(n))return n}function we(n,r){var e=n==null?null:typeof Symbol!="undefined"&&n[Symbol.iterator]||n["@@iterator"];if(e!=null){var t=[],i=!0,$=!1,o,l;try{for(e=e.call(n);!(i=(o=e.next()).done)&&(t.push(o.value),!(r&&t.length===r));i=!0);}catch(f){$=!0,l=f}finally{try{!i&&e.return!=null&&e.return()}finally{if($)throw l}}return t}}function Te(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function Z(n,r){(r==null||r>n.length)&&(r=n.length);for(var e=0,t=new Array(r);e<r;e++)t[e]=n[e];return t}function re(n,r){if(n){if(typeof n=="string")return Z(n,r);var e=Object.prototype.toString.call(n).slice(8,-1);if(e==="Object"&&n.constructor&&(e=n.constructor.name),e==="Map"||e==="Set")return Array.from(e);if(e==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(e))return Z(n,r)}}function ne(n,r){return Se(n)||we(n,r)||re(n,r)||Te()}function Oe(n){if(Array.isArray(n))return Z(n)}function Ie(n){if(typeof Symbol!="undefined"&&n[Symbol.iterator]!=null||n["@@iterator"]!=null)return Array.from(n)}function Ae(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function V(n){return Oe(n)||Ie(n)||re(n)||Ae()}function ie(n){"@swc/helpers - typeof";return n&&typeof Symbol!="undefined"&&n.constructor===Symbol?"symbol":typeof n}function q(n,r){var e={label:0,sent:function(){if($[0]&1)throw $[1];return $[1]},trys:[],ops:[]},t,i,$,o=Object.create((typeof Iterator=="function"?Iterator:Object).prototype);return o.next=l(0),o.throw=l(1),o.return=l(2),typeof Symbol=="function"&&(o[Symbol.iterator]=function(){return this}),o;function l(s){return function(d){return f([s,d])}}function f(s){if(t)throw new TypeError("Generator is already executing.");for(;o&&(o=0,s[0]&&(e=0)),e;)try{if(t=1,i&&($=s[0]&2?i.return:s[0]?i.throw||(($=i.return)&&$.call(i),0):i.next)&&!($=$.call(i,s[1])).done)return $;switch(i=0,$&&(s=[s[0]&2,$.value]),s[0]){case 0:case 1:$=s;break;case 4:return e.label++,{value:s[1],done:!1};case 5:e.label++,i=s[1],s=[0];continue;case 7:s=e.ops.pop(),e.trys.pop();continue;default:if($=e.trys,!($=$.length>0&&$[$.length-1])&&(s[0]===6||s[0]===2)){e=0;continue}if(s[0]===3&&(!$||s[1]>$[0]&&s[1]<$[3])){e.label=s[1];break}if(s[0]===6&&e.label<$[1]){e.label=$[1],$=s;break}if($&&e.label<$[2]){e.label=$[2],e.ops.push(s);break}$[2]&&e.ops.pop(),e.trys.pop();continue}s=r.call(n,e)}catch(d){s=[6,d],i=0}finally{t=$=0}if(s[0]&5)throw s[1];return{value:s[0]?s[1]:void 0,done:!0}}}var Ce="use strict;use warnings;require 5.004;my$version='13.30';$^W=1;my$exePath;BEGIN {$exePath=@ARGV && lc($ARGV[0])eq '-xpath' && shift()? $^X : $0;my$exeDir=($exePath =~ /(.*)[\\\\\\/]/)? $1 : '.';my$incDir=($0 =~ /(.*)[\\\\\\/]/)? \"$1/lib\" : './lib';if (-l $0){my$lnk=eval {readlink $0};if (defined$lnk){my$lnkDir=($lnk =~ /(.*)[\\\\\\/]/)? $1 : '.';$exeDir=(($lnk =~ m(^/))? '' : $exeDir .'/').$lnkDir;$incDir=\"$exeDir/lib\"}}$Image::ExifTool::exeDir=$exeDir;unshift@INC,$incDir;while (@ARGV and lc($ARGV[0])eq '-config'){shift;push@Image::ExifTool::configFiles,shift}}use Image::ExifTool qw{:Public};sub SigInt();sub SigCont();sub Cleanup();sub GetImageInfo($$);sub SetImageInfo($$$);sub DoHardLink($$$$$);sub CleanXML($);sub EncodeXML($);sub FormatXML($$$);sub EscapeJSON($;$);sub FormatJSON($$$;$);sub PrintCSV(;$);sub AddGroups($$$$);sub ConvertBinary($);sub IsEqual($$);sub Printable($);sub LengthUTF8($);sub Infile($;$);sub AddSetTagsFile($;$);sub Warning($$);sub DoSetFromFile($$$);sub CleanFilename($);sub HasWildcards($);sub SetWindowTitle($);sub ProcessFiles($;$);sub ScanDir($$;$);sub FindFileWindows($$);sub FileNotFound($);sub PreserveTime();sub AbsPath($);sub MyConvertFileName($$);sub SuggestedExtension($$$);sub LoadPrintFormat($;$);sub FilenameSPrintf($;$@);sub NextUnusedFilename($;$);sub CreateDirectory($);sub OpenOutputFile($;@);sub AcceptFile($);sub SlurpFile($$);sub FilterArgfileLine($);sub ReadStayOpen($);sub Progress($$);sub PrintTagList($@);sub PrintErrors($$$);$SIG{INT}='SigInt';$SIG{CONT}='SigCont';END {Cleanup()}my@commonArgs;my@condition;my@csvFiles;my@csvTags;my@delFiles;my@dynamicFiles;my@efile;my@exclude;my (@echo3,@echo4);my@files;my@moreArgs;my@newValues;my@requestTags;my@srcFmt;my@tags;my%altFile;my%appended;my%countLink;my%created;my%csvTags;my%database;my%filterExt;my%ignore;my$ignoreHidden;my%outComma;my%outTrailer;my%preserveTime;my%printFmt;my%seqFileDir;my%setTags;my%setTagsList;my%usedFileName;my%utf8FileName;my%warnedOnce;my%wext;my$allGroup;my$altEnc;my$argFormat;my$binaryOutput;my$binaryStdout;my$binSep;my$binTerm;my$comma;my$count;my$countBad;my$countBadCr;my$countBadWr;my$countCopyWr;my$countDir;my$countFailed;my$countGoodCr;my$countGoodWr;my$countNewDir;my$countSameWr;my$critical;my$csv;my$csvAdd;my$csvDelim;my$csvSaveCount;my$deleteOrig;my$diff;my$disableOutput;my$doSetFileName;my$doUnzip;my ($end,$endDir,%endDir);my$escapeC;my$escapeHTML;my$evalWarning;my$executeID;my$failCondition;my$fastCondition;my$fileHeader;my$fileTrailer;my$filtered;my$filterFlag;my$fixLen;my$forcePrint;my$geoOnly;my$helped;my$html;my$interrupted;my$isBinary;my$isWriting;my$joinLists;my$json;my$langOpt;my$listDir;my$listItem;my$listSep;my$mt;my$multiFile;my$noBinary;my$outFormat;my$outOpt;my$overwriteOrig;my$pause;my$plot;my$preserveTime;my$progress;my$progressCount;my$progressIncr;my$progressMax;my$progressNext;my$progStr;my$quiet;my$rafStdin;my$recurse;my$rtnVal;my$rtnValPrev;my$saveCount;my$scanWritable;my$sectHeader;my$sectTrailer;my$seqFileDir;my$seqFileNum;my$setCharset;my$showGroup;my$showTagID;my$stayOpenBuff='';my$stayOpenFile;my$structOpt;my$tabFormat;my$tagOut;my$textOut;my$textOut2;my$textOverwrite;my$tmpFile;my$tmpText;my$validFile;my$verbose;my$vout;my$windowTitle;my%wroteHEAD;my$xml;my$stayOpen=0;my$rtnValApp=0;my$curTitle='';my$isCRLF={MSWin32=>1,os2=>1,dos=>1 }->{$^O};my%jsonChar=('\"'=>'\"','\\\\'=>'\\\\',\"\\t\"=>'t',\"\\n\"=>'n',\"\\r\"=>'r');my%escC=(\"\\n\"=>'\\n',\"\\r\"=>'\\r',\"\\t\"=>'\\t','\\\\'=>'\\\\\\\\');my%unescC=(a=>\"\\a\",b=>\"\\b\",f=>\"\\f\",n=>\"\\n\",r=>\"\\r\",t=>\"\\t\",0=>\"\\0\",'\\\\'=>'\\\\');my%optArgs=('-tagsfromfile'=>1,'-addtagsfromfile'=>1,'-alltagsfromfile'=>1,'-@'=>1,'-api'=>1,'-c'=>1,'-coordformat'=>1,'-charset'=>0,'-config'=>1,'-csvdelim'=>1,'-d'=>1,'-dateformat'=>1,'-D'=>0,'-diff'=>1,'-echo'=>1,'-echo#'=>1,'-efile'=>1,'-efile#'=>1,'-efile!'=>1,'-efile#!'=>1,'-ext'=>1,'--ext'=>1,'-ext+'=>1,'--ext+'=>1,'-extension'=>1,'--extension'=>1,'-extension+'=>1,'--extension+'=>1,'-fileorder'=>1,'-fileorder#'=>1,'-file#'=>1,'-geotag'=>1,'-globaltimeshift'=>1,'-i'=>1,'-ignore'=>1,'-if'=>1,'-if#'=>1,'-lang'=>0,'-listitem'=>1,'-o'=>1,'-out'=>1,'-p'=>1,'-printformat'=>1,'-p-'=>1,'-printformat-'=>1,'-P'=>0,'-password'=>1,'-require'=>1,'-sep'=>1,'-separator'=>1,'-srcfile'=>1,'-stay_open'=>1,'-use'=>1,'-userparam'=>1,'-w'=>1,'-w!'=>1,'-w+'=>1,'-w+!'=>1,'-w!+'=>1,'-textout'=>1,'-textout!'=>1,'-textout+'=>1,'-textout+!'=>1,'-textout!+'=>1,'-tagout'=>1,'-tagout!'=>1,'-tagout+'=>1,'-tagout+!'=>1,'-tagout!+'=>1,'-wext'=>1,'-wm'=>1,'-writemode'=>1,'-x'=>1,'-exclude'=>1,'-X'=>0,);my@recommends=qw(Archive::Zip Compress::Zlib Digest::MD5 Digest::SHA IO::Compress::Bzip2 POSIX::strptime Time::Local Unicode::LineBreak Compress::Raw::Lzma IO::Compress::RawDeflate IO::Uncompress::RawInflate IO::Compress::Brotli IO::Uncompress::Brotli Win32::API Win32::FindFile Win32API::File);my%altRecommends=('POSIX::strptime'=>'Time::Piece',);my%unescapeChar=('t'=>\"\\t\",'n'=>\"\\n\",'r'=>\"\\r\");sub Image::ExifTool::EndDir() {return$endDir=1}sub Image::ExifTool::End() {return$end=1}sub Exit {if ($pause){if (eval {require Term::ReadKey}){print STDERR \"-- press any key --\";Term::ReadKey::ReadMode('cbreak');Term::ReadKey::ReadKey(0);Term::ReadKey::ReadMode(0);print STDERR \"\\b \\b\" x 20}else {print STDERR \"-- press RETURN --\\n\";<STDIN>}}exit shift}sub Warn {if ($quiet < 2 or $_[0]=~ /^Error/){my$oldWarn=$SIG{'__WARN__'};delete$SIG{'__WARN__'};warn(@_);$SIG{'__WARN__'}=$oldWarn if defined$oldWarn}}sub Error {Warn @_;$rtnVal=1}sub WarnOnce($) {Warn(@_)and $warnedOnce{$_[0]}=1 unless$warnedOnce{$_[0]}}sub SigInt() {$critical and $interrupted=1,return;Cleanup();exit 1}sub SigCont() {}sub Cleanup() {$mt->Unlink($tmpFile)if defined$tmpFile;$mt->Unlink($tmpText)if defined$tmpText;undef$tmpFile;undef$tmpText;PreserveTime()if%preserveTime;SetWindowTitle('')}if (grep /^-common_args$/i,@ARGV){my (@newArgs,$common,$end);for (@ARGV){if (/^-common_args$/i and not $end){$common=1}elsif ($common){push@commonArgs,$_}else {$end=1 if $_ eq '--';push@newArgs,$_}}@ARGV=@newArgs if$common}Command: for (;;){if (@echo3){my$str=join(\"\\n\",@echo3).\"\\n\";$str =~ s/\\$\\{status\\}/$rtnVal/ig;print STDOUT$str}if (@echo4){my$str=join(\"\\n\",@echo4).\"\\n\";$str =~ s/\\$\\{status\\}/$rtnVal/ig;print STDERR$str}$rafStdin->Close()if$rafStdin;undef$rafStdin;$rtnValPrev=$rtnVal;$rtnValApp=$rtnVal if$rtnVal;last unless@ARGV or not defined$rtnVal or $stayOpen >= 2 or @commonArgs;if ($binaryStdout){binmode(STDOUT,':crlf')if $] >= 5.006 and $isCRLF;$binaryStdout=0}if ($stayOpen >= 2){if ($quiet and not defined$executeID){eval {require IO::Handle}and STDERR->flush(),STDOUT->flush()}else {eval {require IO::Handle}and STDERR->flush();my$id=defined$executeID ? $executeID : '';my$save=$|;$|=1;print \"{ready$id}\\n\";$|=$save}}undef@condition;undef@csvFiles;undef@csvTags;undef@delFiles;undef@dynamicFiles;undef@echo3;undef@echo4;undef@efile;undef@exclude;undef@files;undef@newValues;undef@srcFmt;undef@tags;undef%appended;undef%countLink;undef%created;undef%csvTags;undef%database;undef%endDir;undef%filterExt;undef%ignore;undef%outComma;undef%outTrailer;undef%preserveTime;undef%printFmt;undef%seqFileDir;undef%setTags;undef%setTagsList;undef%usedFileName;undef%utf8FileName;undef%warnedOnce;undef%wext;undef$allGroup;undef$altEnc;undef$argFormat;undef$binaryOutput;undef$binSep;undef$binTerm;undef$comma;undef$csv;undef$csvAdd;undef$deleteOrig;undef$diff;undef$disableOutput;undef$doSetFileName;undef$doUnzip;undef$end;undef$endDir;undef$escapeHTML;undef$escapeC;undef$evalWarning;undef$executeID;undef$failCondition;undef$fastCondition;undef$fileHeader;undef$filtered;undef$fixLen;undef$forcePrint;undef$geoOnly;undef$ignoreHidden;undef$joinLists;undef$langOpt;undef$listItem;undef$multiFile;undef$noBinary;undef$outOpt;undef$preserveTime;undef$progress;undef$progressCount;undef$progressIncr;undef$progressMax;undef$progressNext;undef$recurse;undef$scanWritable;undef$sectHeader;undef$setCharset;undef$showGroup;undef$showTagID;undef$structOpt;undef$tagOut;undef$textOut;undef$textOverwrite;undef$tmpFile;undef$tmpText;undef$validFile;undef$verbose;undef$windowTitle;$count=0;$countBad=0;$countBadCr=0;$countBadWr=0;$countCopyWr=0;$countDir=0;$countFailed=0;$countGoodCr=0;$countGoodWr=0;$countNewDir=0;$countSameWr=0;$csvDelim=',';$csvSaveCount=0;$fileTrailer='';$filterFlag=0;$html=0;$isWriting=0;$json=0;$listSep=', ';$outFormat=0;$overwriteOrig=0;$progStr='';$quiet=0;$rtnVal=0;$saveCount=0;$sectTrailer='';$seqFileDir=0;$seqFileNum=0;$tabFormat=0;$vout=\\*STDOUT;$xml=0;my@fileOrder;my$fileOrderFast;my$addGeotime;my$doGlob;my$endOfOpts;my$escapeXML;my$setTagsFile;my$sortOpt;my$srcStdin;my$useMWG;my ($argsLeft,@nextPass,$badCmd);my$pass=0;if ($^O eq 'MSWin32' and eval {require File::Glob}){import File::Glob qw(:globally :nocase);$doGlob=1}$mt=Image::ExifTool->new;$mt->Options(Duplicates=>0)unless%Image::ExifTool::UserDefined::Options and defined$Image::ExifTool::UserDefined::Options{Duplicates};$joinLists=1 if defined$mt->Options('List')and not $mt->Options('List');if (not $preserveTime and $^O eq 'MSWin32'){$preserveTime=2 if eval {require Win32::API}and eval {require Win32API::File}}if (@Image::ExifTool::UserDefined::Arguments){unshift@ARGV,@Image::ExifTool::UserDefined::Arguments}if ($version ne $Image::ExifTool::VERSION){Warn \"Application version $version does not match Image::ExifTool library version $Image::ExifTool::VERSION\\n\"}for (;;){if (not @ARGV or ($ARGV[0]=~ /^(-|\\xe2\\x88\\x92)execute(\\d+)?$/i and not $endOfOpts)){if (@ARGV){$executeID=$2;$helped=1;$badCmd and shift,$rtnVal=1,next Command}elsif ($stayOpen >= 2){ReadStayOpen(\\@ARGV);next}elsif ($badCmd){undef@commonArgs;$rtnVal=1;next Command}if ($pass==0){if (@commonArgs and not defined$argsLeft){$argsLeft=scalar(@ARGV)+ scalar(@moreArgs);unshift@ARGV,@commonArgs;undef@commonArgs unless$argsLeft;next}if (defined$argsLeft and $argsLeft < scalar(@ARGV)+ scalar(@moreArgs)){Warn \"Ignoring -common_args from $ARGV[0] onwards to avoid infinite recursion\\n\";while ($argsLeft < scalar(@ARGV)+ scalar(@moreArgs)){@ARGV and shift(@ARGV),next;shift@moreArgs}}$useMWG=1 if not $useMWG and grep /^([--_0-9A-Z]+:)*1?mwg:/i,@tags,@requestTags;if ($useMWG){require Image::ExifTool::MWG;Image::ExifTool::MWG::Load()}if (defined$forcePrint){unless (defined$mt->Options('MissingTagValue')){$mt->Options(MissingTagValue=>'-')}$forcePrint=$mt->Options('MissingTagValue')}}if (@nextPass){unshift@ARGV,@nextPass;undef@nextPass;undef$endOfOpts;++$pass;next}@ARGV and shift;last}$_=shift;next if$badCmd;if (not $endOfOpts and s/^(-|\\xe2\\x88\\x92)//){s/^\\xe2\\x88\\x92/-/;if ($_ eq '-'){$pass or push@nextPass,'--';$endOfOpts=1;next}my$a=lc $_;if (/^list([wfrdx]|wf|g(\\d*)|geo)?$/i){$pass or push@nextPass,\"-$_\";my$type=lc($1 || '');if (not $type or $type eq 'w' or $type eq 'x'){my$group;if ($ARGV[0]and $ARGV[0]=~ /^(-|\\xe2\\x88\\x92)(.+):(all|\\*)$/i){if ($pass==0){$useMWG=1 if lc($2)eq 'mwg';push@nextPass,shift;next}$group=$2;shift;$group =~ /IFD/i and Warn(\"Can't list tags for specific IFD\\n\"),$helped=1,next;$group =~ /^(all|\\*)$/ and undef$group}else {$pass or next}$helped=1;if ($type eq 'x'){require Image::ExifTool::TagInfoXML;my%opts;$opts{Flags}=1 if defined$forcePrint;$opts{NoDesc}=1 if$outFormat > 0;$opts{Lang}=$langOpt;Image::ExifTool::TagInfoXML::Write(undef,$group,%opts);next}my$wr=($type eq 'w');my$msg=($wr ? 'Writable' : 'Available').($group ? \" $group\" : '').' tags';PrintTagList($msg,$wr ? GetWritableTags($group): GetAllTags($group));next if$group or $wr;my@tagList=GetShortcuts();PrintTagList('Command-line shortcuts',@tagList)if@tagList;next}$pass or next;$helped=1;if ($type eq 'wf'){my@wf;CanWrite($_)and push@wf,$_ foreach GetFileType();PrintTagList('Writable file extensions',@wf)}elsif ($type eq 'f'){PrintTagList('Supported file extensions',GetFileType())}elsif ($type eq 'r'){PrintTagList('Recognized file extensions',GetFileType(undef,0))}elsif ($type eq 'd'){PrintTagList('Deletable groups',GetDeleteGroups())}elsif ($type eq 'geo'){require Image::ExifTool::Geolocation;my ($i,$entry);print \"Geolocation database:\\n\" unless$quiet;my$isAlt=$mt->Options('GeolocAltNames')? ',AltNames' : '';$isAlt='' if$isAlt and not Image::ExifTool::Geolocation::ReadAltNames();print \"City,Region,Subregion,CountryCode,Country,TimeZone,FeatureCode,Population,Latitude,Longitude$isAlt\\n\";Image::ExifTool::Geolocation::SortDatabase('City')if$sortOpt;my$minPop=$mt->Options('GeolocMinPop');my$feature=$mt->Options('GeolocFeature')|| '';my$neg=$feature =~ s/^-//;my%fcodes=map {lc($_)=>1}split /\\s*,\\s*/,$feature;my@isUTF8=(0,1,2,4);push@isUTF8,10 if$isAlt;for ($i=0;;++$i){my@entry=Image::ExifTool::Geolocation::GetEntry($i,$langOpt,1)or last;$#entry=9;next if$minPop and $entry[7]< $minPop;next if%fcodes and $neg ? $fcodes{lc$entry[6]}: not $fcodes{lc$entry[6]};push@entry,Image::ExifTool::Geolocation::GetAltNames($i,1)if$isAlt;$_=defined $_ ? $mt->Decode($_,'UTF8'): '' foreach@entry[@isUTF8];pop@entry if$isAlt and not $entry[10];print join(',',@entry),\"\\n\"}}else {my$family=$2 || 0;PrintTagList(\"Groups in family $family\",$mt->GetAllGroups($family))}next}if ($a eq 'ver'){$pass or push(@nextPass,'-ver'),next;my$libVer=$Image::ExifTool::VERSION;my$str=$libVer eq $version ? '' : \" [Warning: Library version is $libVer]\";if ($verbose){print \"ExifTool version $version$str$Image::ExifTool::RELEASE\\n\";printf \"Perl version %s%s\\n\",$],(defined ${^UNICODE} ? \" (-C${^UNICODE})\" : '');print \"Platform: $^O\\n\";if ($verbose > 8){print \"Current Dir: \" .Cwd::getcwd().\"\\n\" if (eval {require Cwd});print \"Script Name: $0\\n\";print \"Exe Name: $^X\\n\";print \"Exe Dir: $Image::ExifTool::exeDir\\n\";print \"Exe Path: $exePath\\n\"}print \"Optional libraries:\\n\";for (@recommends){next if /^Win32/ and $^O ne 'MSWin32';my$ver=eval \"require $_ and \\$${_}::VERSION\";my$alt=$altRecommends{$_};$ver=eval \"require $alt and \\$${alt}::VERSION\" and $_=$alt if not $ver and $alt;printf \" %-28s %s\\n\",$_,$ver || '(not installed)'}if ($verbose > 1){print \"Include directories:\\n\";ref $_ or print \" $_\\n\" foreach@INC}}else {print \"$version$str$Image::ExifTool::RELEASE\\n\"}$helped=1;next}if (/^(all|add)?tagsfromfile(=.*)?$/i){$setTagsFile=$2 ? substr($2,1): (@ARGV ? shift : '');if ($setTagsFile eq ''){Error(\"File must be specified for -tagsFromFile option\\n\");$badCmd=1;next}AddSetTagsFile($setTagsFile,{Replace=>($1 and lc($1)eq 'add')? 0 : 1 });next}if ($a eq '@'){my$argFile=shift or Error(\"Expecting filename for -\\@ option\\n\"),$badCmd=1,next;if ($stayOpen==1){@moreArgs=@ARGV;undef@ARGV}elsif ($stayOpen==3){if ($stayOpenFile and $stayOpenFile ne '-' and $argFile eq $stayOpenFile){$stayOpen=2;Warn \"Ignoring request to switch to the same -stay_open ARGFILE ($argFile)\\n\";next}close STAYOPEN;$stayOpen=1}my$fp=($stayOpen==1 ? \\*STAYOPEN : \\*ARGFILE);unless ($mt->Open($fp,$argFile)){unless ($argFile !~ /^\\// and $mt->Open($fp,\"$Image::ExifTool::exeDir/$argFile\")){Error \"Error opening arg file $argFile\\n\";$badCmd=1;next}}if ($stayOpen==1){$stayOpenFile=$argFile;$stayOpenBuff='';$stayOpen=2;$helped=1;ReadStayOpen(\\@ARGV);next}my (@newArgs,$didBOM);for (<ARGFILE>){unless ($didBOM){s/^\\xef\\xbb\\xbf//;$didBOM=1}$_=FilterArgfileLine($_);push@newArgs,$_ if defined $_}close ARGFILE;unshift@ARGV,@newArgs;next}/^(-?)(a|duplicates)$/i and $mt->Options(Duplicates=>($1 ? 0 : 1)),next;if ($a eq 'api'){my$opt=shift;if (defined$opt and length$opt){my$val=($opt =~ s/=(.*)//s)? $1 : 1;$val=undef unless$opt =~ s/\\^$// or length$val;$mt->Options($opt=>$val)}else {print \"Available API Options:\\n\";my$availableOptions=Image::ExifTool::AvailableOptions();$$_[3]or printf(\" %-17s - %s\\n\",$$_[0],$$_[2])foreach @$availableOptions;$helped=1}next}/^arg(s|format)$/i and $argFormat=1,next;if (/^(-?)b(inary)?$/i){($binaryOutput,$noBinary)=$1 ? (undef,1): (1,undef);$mt->Options(Binary=>$binaryOutput,NoPDFList=>$binaryOutput);next}if (/^c(oordFormat)?$/i){my$fmt=shift;$fmt or Error(\"Expecting coordinate format for -c option\\n\"),$badCmd=1,next;$mt->Options('CoordFormat',$fmt);next}if ($a eq 'charset'){my$charset=(@ARGV and $ARGV[0]!~ /^(-|\\xe2\\x88\\x92)/)? shift : undef;if (not $charset){$pass or push(@nextPass,'-charset'),next;my%charsets;$charsets{$_}=1 foreach values%Image::ExifTool::charsetName;PrintTagList('Available character sets',sort keys%charsets);$helped=1}elsif ($charset !~ s/^(\\w+)=// or lc($1)eq 'exiftool'){{local$SIG{'__WARN__'}=sub {$evalWarning=$_[0]};undef$evalWarning;$mt->Options(Charset=>$charset)}if ($evalWarning){Warn$evalWarning}else {$setCharset=$mt->Options('Charset')}}else {my$type={id3=>'ID3',iptc=>'IPTC',exif=>'EXIF',filename=>'FileName',photoshop=>'Photoshop',quicktime=>'QuickTime',riff=>'RIFF' }->{lc $1};$type or Warn(\"Unknown type for -charset option: $1\\n\"),next;$mt->Options(\"Charset$type\"=>$charset)}next}/^config$/i and Warn(\"Ignored -config option (not first on command line)\\n\"),shift,next;if (/^csv(\\+?=.*)?$/i){my$csvFile=$1;unless ($pass){push@nextPass,\"-$_\";if ($csvFile){push@newValues,{SaveCount=>++$saveCount };$csvSaveCount=$saveCount}next}if ($csvFile){$csvFile =~ s/^(\\+?=)//;$csvAdd=2 if $1 eq '+=';$vout=\\*STDERR if$srcStdin;$verbose and print$vout \"Reading CSV file $csvFile\\n\";my$msg;if ($mt->Open(\\*CSVFILE,$csvFile)){binmode CSVFILE;require Image::ExifTool::Import;$msg=Image::ExifTool::Import::ReadCSV(\\*CSVFILE,\\%database,$forcePrint,$csvDelim);close(CSVFILE)}else {$msg=\"Error opening CSV file '${csvFile}'\"}$msg and Warn(\"$msg\\n\");$isWriting=1}$csv='CSV';next}if (/^csvdelim$/i){$csvDelim=shift;defined$csvDelim or Error(\"Expecting argument for -csvDelim option\\n\"),$badCmd=1,next;$csvDelim =~ /\"/ and Error(\"CSV delimiter can not contain a double quote\\n\"),$badCmd=1,next;my%unescape=('t'=>\"\\t\",'n'=>\"\\n\",'r'=>\"\\r\",'\\\\'=>'\\\\');$csvDelim =~ s/\\\\(.)/$unescape{$1}||\"\\\\$1\"/sge;$mt->Options(CSVDelim=>$csvDelim);next}if (/^d$/ or $a eq 'dateformat'){my$fmt=shift;$fmt or Error(\"Expecting date format for -d option\\n\"),$badCmd=1,next;$mt->Options('DateFormat',$fmt);next}(/^D$/ or $a eq 'decimal')and $showTagID='D',next;if (/^diff$/i){$diff=shift;defined$diff or Error(\"Expecting file name for -$_ option\\n\"),$badCmd=1;next}/^delete_original(!?)$/i and $deleteOrig=($1 ? 2 : 1),next;/^list_dir$/i and $listDir=1,next;(/^e$/ or $a eq '-composite')and $mt->Options(Composite=>0),next;(/^-e$/ or $a eq 'composite')and $mt->Options(Composite=>1),next;(/^E$/ or $a eq 'escapehtml')and require Image::ExifTool::HTML and $escapeHTML=1,next;($a eq 'ec' or $a eq 'escapec')and $escapeC=1,next;($a eq 'ex' or $a eq 'escapexml')and $escapeXML=1,next;if (/^echo(\\d)?$/i){my$n=$1 || 1;my$arg=shift;next unless defined$arg;$n > 4 and Warn(\"Invalid -echo number\\n\"),next;if ($n > 2){$n==3 ? push(@echo3,$arg): push(@echo4,$arg)}else {print {$n==2 ? \\*STDERR : \\*STDOUT}$arg,\"\\n\"}$helped=1;next}if (/^(ee|extractembedded)(\\d*)$/i){$mt->Options(ExtractEmbedded=>$2 || 1);$mt->Options(Duplicates=>1);next}if (/^efile(\\d+)?(!)?$/i){my$arg=shift;defined$arg or Error(\"Expecting file name for -$_ option\\n\"),$badCmd=1,next;$efile[0]=$arg if not $1 or $1 & 0x01;$efile[1]=$arg if $1 and $1 & 0x02;$efile[2]=$arg if $1 and $1 & 0x04;$efile[3]=$arg if $1 and $1 & 0x08;$efile[4]=$arg if $1 and $1 & 0x016;unlink$arg if $2;next}if (/^-?ext(ension)?(\\+)?$/i){my$ext=shift;defined$ext or Error(\"Expecting extension for -ext option\\n\"),$badCmd=1,next;my$flag=/^-/ ? 0 : ($2 ? 2 : 1);$filterFlag |= (0x01 << $flag);$ext =~ s/^\\.//;$filterExt{uc($ext)}=$flag ? 1 : 0;next}if (/^f$/ or $a eq 'forceprint'){$forcePrint=1;next}if (/^F([-+]?\\d*)$/ or /^fixbase([-+]?\\d*)$/i){$mt->Options(FixBase=>$1);next}if (/^fast(\\d*)$/i){$mt->Options(FastScan=>(length $1 ? $1 : 1));next}if (/^(file\\d+)$/i){$altFile{lc $1}=shift or Error(\"Expecting file name for -file option\\n\"),$badCmd=1,next;next}if (/^fileorder(\\d*)$/i){push@fileOrder,shift if@ARGV;my$num=$1 || 0;$fileOrderFast=$num if not defined$fileOrderFast or $fileOrderFast > $num;next}$a eq 'globaltimeshift' and $mt->Options(GlobalTimeShift=>shift),next;if (/^(g)(roupHeadings|roupNames)?([\\d:]*)$/i){$showGroup=$3 || 0;$allGroup=($2 ? lc($2)eq 'roupnames' : $1 eq 'G');$mt->Options(SavePath=>1)if$showGroup =~ /\\b5\\b/;$mt->Options(SaveFormat=>1)if$showGroup =~ /\\b6\\b/;next}if ($a eq 'geotag'){my$trkfile=shift;unless ($pass){push@nextPass,'-geotag',$trkfile;next}$trkfile or Error(\"Expecting file name for -geotag option\\n\"),$badCmd=1,next;if (HasWildcards($trkfile)){my@trks;if ($^O eq 'MSWin32' and eval {require Win32::FindFile}){@trks=FindFileWindows($mt,$trkfile)}elsif (eval {require File::Glob}){@trks=File::Glob::bsd_glob($trkfile)}else {@trks=glob($trkfile)}@trks or Error(\"No matching file found for -geotag option\\n\"),$badCmd=1,next;push@newValues,'geotag='.shift(@trks)while@trks > 1;$trkfile=pop(@trks)}$_=\"geotag=$trkfile\"}if (/^h$/ or $a eq 'htmlformat'){require Image::ExifTool::HTML;$html=$escapeHTML=1;$json=$xml=0;next}(/^H$/ or $a eq 'hex')and $showTagID='H',next;if (/^htmldump([-+]?\\d+)?$/i){$verbose=($verbose || 0)+ 1;$html=2;$mt->Options(HtmlDumpBase=>$1)if defined $1;next}if (/^i(gnore)?$/i){my$dir=shift;defined$dir or Error(\"Expecting directory name for -i option\\n\"),$badCmd=1,next;$ignore{$dir}=1;$dir eq 'HIDDEN' and $ignoreHidden=1;next}if (/^if(\\d*)$/i){my$cond=shift;my$fast=length($1)? $1 : undef;defined$cond or Error(\"Expecting expression for -if option\\n\"),$badCmd=1,next;if (not @condition or not defined$fast or (defined$fastCondition and $fastCondition > $fast)){$fastCondition=$fast}$cond =~ /^\\s*(not\\s*)\\$ok\\s*$/i and ($1 xor $rtnValPrev)and $failCondition=1;push@requestTags,$cond =~ /\\$\\{?((?:[-_0-9A-Z]+:)*[-_0-9A-Z?*]+)/ig;push@condition,$cond;next}if (/^j(son)?(\\+?=.*)?$/i){if ($2){unless ($pass){push@nextPass,\"-$_\";push@newValues,{SaveCount=>++$saveCount };$csvSaveCount=$saveCount;next}my$jsonFile=$2;$jsonFile =~ s/^(\\+?=)//;$csvAdd=2 if $1 eq '+=';$vout=\\*STDERR if$srcStdin;$verbose and print$vout \"Reading JSON file $jsonFile\\n\";my$chset=$mt->Options('Charset');my$msg;if ($mt->Open(\\*JSONFILE,$jsonFile)){binmode JSONFILE;require Image::ExifTool::Import;$msg=Image::ExifTool::Import::ReadJSON(\\*JSONFILE,\\%database,$forcePrint,$chset);close(JSONFILE)}else {$msg=\"Error opening JSON file '${jsonFile}'\"}$msg and Warn(\"$msg\\n\");$isWriting=1;$csv='JSON'}else {$json=1;$html=$xml=0;$mt->Options(Duplicates=>1);require Image::ExifTool::XMP}next}/^(k|pause)$/i and $pause=1,next;(/^l$/ or $a eq 'long')and --$outFormat,next;(/^L$/ or $a eq 'latin')and $mt->Options(Charset=>'Latin'),next;if ($a eq 'lang'){$langOpt=(@ARGV and $ARGV[0]!~ /^(-|\\xe2\\x88\\x92)/)? shift : undef;if ($langOpt){$langOpt =~ tr/-A-Z/_a-z/;$mt->Options(Lang=>$langOpt);next if$langOpt eq $mt->Options('Lang')}else {$pass or push(@nextPass,'-lang'),next}my$langs=$quiet ? '' : \"Available languages:\\n\";$langs .= \" $_ - $Image::ExifTool::langName{$_}\\n\" foreach@Image::ExifTool::langs;$langs =~ tr/_/-/;$langs=Image::ExifTool::HTML::EscapeHTML($langs)if$escapeHTML;$langs=$mt->Decode($langs,'UTF8');$langOpt and Error(\"Invalid or unsupported language '${langOpt}'.\\n$langs\"),$badCmd=1,next;print$langs;$helped=1;next}if ($a eq 'listitem'){my$li=shift;defined$li and Image::ExifTool::IsInt($li)or Warn(\"Expecting integer for -listItem option\\n\"),next;$mt->Options(ListItem=>$li);$listItem=$li;next}/^(m|ignoreminorerrors)$/i and $mt->Options(IgnoreMinorErrors=>1),next;/^(n|-printconv)$/i and $mt->Options(PrintConv=>0),next;/^(-n|printconv)$/i and $mt->Options(PrintConv=>1),next;$a eq 'nop' and $helped=1,next;if (/^o(ut)?$/i){$outOpt=shift;defined$outOpt or Error(\"Expected output file or directory name for -o option\\n\"),$badCmd=1,next;CleanFilename($outOpt);$vout=\\*STDERR if$vout =~ /^-(\\.\\w+)?$/;next}/^overwrite_original$/i and $overwriteOrig=1,next;/^overwrite_original_in_place$/i and $overwriteOrig=2,next;/^plot$/i and require Image::ExifTool::Plot and $plot=Image::ExifTool::Plot->new,next;if (/^p(-?)$/ or /^printformat(-?)$/i){my$fmt=shift;if ($pass){LoadPrintFormat($fmt,$1 || $binaryOutput);if (not $useMWG and grep /^([-_0-9A-Z]+:)*1?mwg:/i,@requestTags){$useMWG=1;require Image::ExifTool::MWG;Image::ExifTool::MWG::Load()}}else {push@nextPass,\"-$_\",$fmt}next}(/^P$/ or $a eq 'preserve')and $preserveTime=1,next;/^password$/i and $mt->Options(Password=>shift),next;if (/^progress(\\d*)(:.*)?$/i){$progressIncr=$1 || 1;$progressNext=0;if ($2){$windowTitle=substr $2,1;$windowTitle='ExifTool %p%%' unless length$windowTitle;$windowTitle =~ /%\\d*[bpr]/ and $progress=0 unless defined$progress}else {$progress=1;$verbose=0 unless defined$verbose}$progressCount=0;next}/^q(uiet)?$/i and ++$quiet,next;/^r(ecurse)?(\\.?)$/i and $recurse=($2 ? 2 : 1),next;if ($a eq 'require'){my$ver=shift;unless (defined$ver and Image::ExifTool::IsFloat($ver)){Error(\"Expecting version number for -require option\\n\");$badCmd=1;next}unless ($Image::ExifTool::VERSION >= $ver){Error(\"Requires ExifTool version $ver or later\\n\");$badCmd=1}next}/^restore_original$/i and $deleteOrig=0,next;(/^S$/ or $a eq 'veryshort')and $outFormat+=2,next;/^s(hort)?(\\d*)$/i and $outFormat=$2 eq '' ? $outFormat + 1 : $2,next;/^scanforxmp$/i and $mt->Options(ScanForXMP=>1),next;if (/^sep(arator)?$/i){my$sep=$listSep=shift;defined$listSep or Error(\"Expecting list item separator for -sep option\\n\"),$badCmd=1,next;$sep =~ s/\\\\(.)/$unescapeChar{$1}||$1/sge;(defined$binSep ? $binTerm : $binSep)=$sep;$mt->Options(ListSep=>$listSep);$joinLists=1;my$listSplit=quotemeta$listSep;$listSplit =~ s/(\\\\ )+/\\\\s\\*/g;$listSplit='\\\\s+' if$listSplit eq '\\\\s*';$mt->Options(ListSplit=>$listSplit);next}/^(-)?sort$/i and $sortOpt=$1 ? 0 : 1,next;if ($a eq 'srcfile'){@ARGV or Warn(\"Expecting FMT for -srcfile option\\n\"),next;push@srcFmt,shift;next}if ($a eq 'stay_open'){my$arg=shift;defined$arg or Warn(\"Expecting argument for -stay_open option\\n\"),next;if ($arg =~ /^(1|true)$/i){if (not $stayOpen){$stayOpen=1}elsif ($stayOpen==2){$stayOpen=3}else {Warn \"-stay_open already active\\n\"}}elsif ($arg =~ /^(0|false)$/i){if ($stayOpen >= 2){close STAYOPEN;push@ARGV,@moreArgs;undef@moreArgs}elsif (not $stayOpen){Warn(\"-stay_open wasn't active\\n\")}$stayOpen=0}else {Warn \"Invalid argument for -stay_open\\n\"}next}if (/^(-)?struct$/i){$mt->Options(Struct=>$1 ? 0 : 1);next}/^t(ab)?$/ and $tabFormat=1,next;if (/^T$/ or $a eq 'table'){$tabFormat=$forcePrint=1;$outFormat+=2;++$quiet;next}if (/^(u)(nknown(2)?)?$/i){my$inc=($3 or (not $2 and $1 eq 'U'))? 2 : 1;$mt->Options(Unknown=>$mt->Options('Unknown')+ $inc);next}if ($a eq 'use'){my$module=shift;$module or Error(\"Expecting module name for -use option\\n\"),$badCmd=1,next;lc$module eq 'mwg' and $useMWG=1,next;$module =~ /[^\\w:]/ and Error(\"Invalid module name: $module\\n\"),$badCmd=1,next;local$SIG{'__WARN__'}=sub {$evalWarning=$_[0]};unless (eval \"require Image::ExifTool::$module\" or eval \"require $module\" or eval \"require '${module}'\"){Error(\"Error using module $module\\n\");$badCmd=1}next}if ($a eq 'userparam'){my$opt=shift;defined$opt or Error(\"Expected parameter for -userParam option\\n\"),$badCmd=1,next;$opt =~ /=/ or $opt .= '=1';$mt->Options(UserParam=>$opt);next}if (/^v(erbose)?(\\d*)$/i){$verbose=($2 eq '')? ($verbose || 0)+ 1 : $2;next}if (/^(w|textout|tagout)([!+]*)$/i){$textOut=shift || Warn(\"Expecting argument for -$_ option\\n\");my ($t1,$t2)=($1,$2);$textOverwrite=0;$textOverwrite += 1 if$t2 =~ /!/;$textOverwrite += 2 if$t2 =~ /\\+/;if ($t1 ne 'W' and lc($t1)ne 'tagout'){undef$tagOut}elsif ($textOverwrite >= 2 and $textOut !~ /%[-+]?\\d*[.:]?\\d*[lu]?[tgso]/){$tagOut=0}else {$tagOut=1}next}if (/^(-?)(wext|tagoutext)$/i){my$ext=shift;defined$ext or Error(\"Expecting extension for -wext option\\n\"),$badCmd=1,next;my$flag=1;$1 and $wext{'*'}=1,$flag=-1;$ext =~ s/^\\.//;$wext{lc$ext}=$flag;next}if ($a eq 'wm' or $a eq 'writemode'){my$wm=shift;defined$wm or Error(\"Expecting argument for -$_ option\\n\"),$badCmd=1,next;$wm =~ /^[wcg]*$/i or Error(\"Invalid argument for -$_ option\\n\"),$badCmd=1,next;$mt->Options(WriteMode=>$wm);next}if (/^x$/ or $a eq 'exclude'){my$tag=shift;defined$tag or Error(\"Expecting tag name for -x option\\n\"),$badCmd=1,next;$tag =~ s/\\ball\\b/\\*/ig;if ($setTagsFile){push @{$setTags{$setTagsFile}},\"-$tag\"}else {push@exclude,$tag}next}(/^X$/ or $a eq 'xmlformat')and $xml=1,$html=$json=0,$mt->Options(Duplicates=>1),next;if (/^php$/i){$json=2;$html=$xml=0;$mt->Options(Duplicates=>1);next}if (/^z(ip)?$/i){$doUnzip=1;$mt->Options(Compress=>1,XMPShorthand=>1);$mt->Options(Compact=>1)unless$mt->Options('Compact');next}$_ eq '' and push(@files,'-'),$srcStdin=1,next;length $_ eq 1 and $_ ne '*' and Error(\"Unknown option -$_\\n\"),$badCmd=1,next;if (/^[^<]+(<?)=(.*)/s){my$val=$2;if ($1 and length($val)and ($val eq '@' or not defined FilenameSPrintf($val))){push@newValues,{SaveCount=>++$saveCount }}push@newValues,$_;if (/^([-_0-9A-Z]+:)*1?mwg:/i){$useMWG=1}elsif (/^([-_0-9A-Z]+:)*(filename|directory|testname)\\b/i){$doSetFileName=1}elsif (/^([-_0-9A-Z]+:)*(geotag|geotime|geosync|geolocate)\\b/i){if (lc $2 eq 'geotime'){$addGeotime=''}else {unshift@newValues,pop@newValues;if (lc $2 eq 'geotag' and (not defined$addGeotime or $addGeotime)and length$val){$addGeotime=($1 || '').q[Geotime<${DateTimeOriginal#;$_=$self->GetValue('SubSecDateTimeOriginal','ValueConv') || $_}]}}}}else {AddSetTagsFile($setTagsFile='@')if not $setTagsFile and /(<|>)/;if ($setTagsFile){push @{$setTags{$setTagsFile}},$_;if ($1 eq '>'){$useMWG=1 if /^(.*>\\s*)?([-_0-9A-Z]+:)*1?mwg:/si;if (/\\b(filename|directory|testname)#?$/i){$doSetFileName=1}elsif (/\\bgeotime#?$/i){$addGeotime=''}}else {$useMWG=1 if /^([^<]+<\\s*(.*\\$\\{?)?)?([-_0-9A-Z]+:)*1?mwg:/si;if (/^([-_0-9A-Z]+:)*(filename|directory|testname)\\b/i){$doSetFileName=1}elsif (/^([-_0-9A-Z]+:)*geotime\\b/i){$addGeotime=''}}}else {my$lst=s/^-// ? \\@exclude : \\@tags;Warn(qq(Invalid TAG name: \"$_\"\\n))unless /^([-_0-9A-Z*]+:)*([-_0-9A-Z*?]+)#?$/i;push @$lst,$_}}}else {unless ($pass){push@nextPass,$_;next}if ($doGlob and HasWildcards($_)){if ($^O eq 'MSWin32' and eval {require Win32::FindFile}){push@files,FindFileWindows($mt,$_)}else {push@files,File::Glob::bsd_glob($_)}$doGlob=2}else {push@files,$_;$srcStdin=1 if $_ eq '-'}}}$mt->Options(UserParam=>'OK=' .(not $rtnValPrev));$vout=\\*STDERR if$srcStdin and ($isWriting or @newValues);$mt->Options(TextOut=>$vout)if$vout eq \\*STDERR;if ($useMWG and not defined$mt->Options('CharsetEXIF')){$mt->Options(CharsetEXIF=>'UTF8')}if (not @files and not $outOpt and not @newValues){my$loc=$mt->Options('Geolocation');$loc and $loc ne '1' and push(@files,qq(\\@JSON:{})),$geoOnly=1}unless ((@tags and not $outOpt)or @files or @newValues or $geoOnly){if ($doGlob and $doGlob==2){Error \"No matching files\\n\";next}$outOpt and Error(\"Nothing to write\\n\"),next;unless ($helped){local$SIG{'__WARN__'}=sub {$evalWarning=$_[0]};my$dummy=\\*SAVEERR;unless ($^O eq 'os2'){open SAVEERR,\">&STDERR\";open STDERR,'>/dev/null'}if (system('perldoc',$0)){print \"Syntax: exiftool [OPTIONS] FILE\\n\\n\";print \"Consult the exiftool documentation for a full list of options.\\n\"}unless ($^O eq 'os2'){close STDERR;open STDERR,'>&SAVEERR'}}next}if (defined$deleteOrig and (@newValues or @tags)){if (not @newValues){my$verb=$deleteOrig ? 'deleting' : 'restoring from';Error \"Can't specify tags when $verb originals\\n\"}elsif ($deleteOrig){Error \"Can't use -delete_original when writing.\\n\";Error \"Maybe you meant -overwrite_original ?\\n\"}else {Error \"It makes no sense to use -restore_original when writing\\n\"}next}if ($overwriteOrig > 1 and $outOpt){Error \"Can't overwrite in place when -o option is used\\n\";next}if (($tagOut or defined$diff)and ($csv or $json or %printFmt or $tabFormat or $xml or $plot or ($verbose and $html))){my$opt=$tagOut ? '-W' : '-diff';Error \"Sorry, $opt may not be combined with -csv, -htmlDump, -j, -p, -t or -X\\n\";next}if ($csv and $csv eq 'CSV' and not $isWriting){$json=0;if ($textOut){$textOut2=$textOut;undef$textOut}if ($binaryOutput){$binaryOutput=0;$setCharset='default' unless defined$setCharset}if (%printFmt){Warn \"The -csv option has no effect when -p is used\\n\";undef$csv}require Image::ExifTool::XMP if$setCharset}if ($plot and $textOut){$textOut2=$textOut;undef$textOut}if ($textOut2){if ($textOverwrite > 1){Error \"Can not append to multi-file output format\\n\";undef$textOut2;next}if (not $textOverwrite and $mt->Exists($textOut2,1)){Error \"Output file $textOut2 already exists\\n\";undef$textOut2;next}CreateDirectory($textOut2);if ($mt->Open(\\*OUTFILE,$textOut2,'>')){close(\\*OUTFILE);unlink($textOut2)}else {Error(\"Error creating $textOut2\\n\");undef$textOut2;next}}if ($escapeHTML or $json){$mt->Options(Charset=>'UTF8')if$json;$mt->Options(Escape=>'HTML')if$escapeHTML and not $xml}elsif ($escapeXML and not $xml){$mt->Options(Escape=>'XML')}if ($sortOpt){my$sort=($outFormat > 0 or $xml or $json or $csv or $plot)? 'Tag' : 'Descr';$mt->Options(Sort=>$sort,Sort2=>$sort)}if ($mt->Options('Struct')and not $structOpt){$structOpt=$mt->Options('Struct');require 'Image/ExifTool/XMPStruct.pl'}if ($plot){undef$joinLists;$mt->Options(List=>1);$plot->Settings($mt->Options('Plot'))}elsif ($xml){require Image::ExifTool::XMP;my$charset=$mt->Options('Charset');my%encoding=(UTF8=>'UTF-8',Latin=>'windows-1252',Latin2=>'windows-1250',Cyrillic=>'windows-1251',Greek=>'windows-1253',Turkish=>'windows-1254',Hebrew=>'windows-1255',Arabic=>'windows-1256',Baltic=>'windows-1257',Vietnam=>'windows-1258',MacRoman=>'macintosh',);unless ($encoding{$charset}){$charset='UTF8';$mt->Options(Charset=>$charset)}$fileHeader=\"<?xml version='1.0' encoding='$encoding{$charset}'?>\\n\" .\"<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>\\n\";$fileTrailer=\"</rdf:RDF>\\n\";$joinLists=1 if$outFormat > 0;$mt->Options(List=>1)unless$joinLists;$showGroup=$allGroup=1;$binaryOutput=($outFormat > 0 ? undef : 0)if$binaryOutput;$showTagID='D' if$tabFormat and not $showTagID}elsif ($json){if ($json==1){$fileHeader='[';$fileTrailer=\"]\\n\"}else {$fileHeader='Array(';$fileTrailer=\");\\n\"}if ($binaryOutput){$binaryOutput=0;require Image::ExifTool::XMP if$json==1}$mt->Options(List=>1)unless$joinLists;$showTagID='D' if$tabFormat and not $showTagID}elsif ($structOpt){$mt->Options(List=>1)}else {$joinLists=1}if ($argFormat){$outFormat=3;$allGroup=1 if defined$showGroup}if (Image::ExifTool::IsPC()){tr/\\\\/\\// foreach@files}unless (@files){unless ($outOpt){if ($doGlob and $doGlob==2){Error \"No matching files\\n\"}else {Error \"No file specified\\n\"}next}push@files,''}if ($verbose){$disableOutput=1 unless@tags or @exclude or $tagOut;undef$binaryOutput unless$tagOut;if ($html){$html=2;$mt->Options(HtmlDump=>$verbose)}else {$mt->Options(Verbose=>$verbose)unless$tagOut}}elsif (defined$verbose){require FileHandle;STDOUT->autoflush(1);STDERR->autoflush(1)}my$needSave=1;if (@newValues){if ($addGeotime){AddSetTagsFile($setTagsFile='@')unless$setTagsFile and $setTagsFile eq '@';push @{$setTags{$setTagsFile}},$addGeotime;$verbose and print$vout qq(Using default \"-$addGeotime\"\\n)}my%setTagsIndex;my%addDelOpt=('+'=>'AddValue','-'=>'DelValue',\"\\xe2\\x88\\x92\"=>'DelValue');$saveCount=0;for (@newValues){if (ref $_ eq 'HASH'){if ($$_{SaveCount}){$saveCount=$mt->SaveNewValues();$needSave=0;push@dynamicFiles,\\$csv if $$_{SaveCount}==$csvSaveCount}next}/(.*?)=(.*)/s or next;\n my ($tag, $newVal) = ($1, $2);\n $tag =~ s/\\ball\\b/\\*/ig; # replace 'all' with '*' in tag names\n $newVal eq '' and undef $newVal unless $tag =~ s/\\^([-+]*)$/$1/; # undefined to delete tag\n if ($tag =~ /^(All)?TagsFromFile$/i){defined$newVal or Error(\"Need file name for -tagsFromFile\\n\"),next Command;++$isWriting;if ($newVal eq '@' or not defined FilenameSPrintf($newVal)or grep /\\bfile\\d+:/i,@{$setTags{$newVal}}){push@dynamicFiles,$newVal;next}unless ($mt->Exists($newVal)or $newVal eq '-'){Error \"File '${newVal}' does not exist for -tagsFromFile option\\n\";next Command}my$setTags=$setTags{$newVal};if ($setTagsList{$newVal}){my$i=$setTagsIndex{$newVal}|| 0;$setTagsIndex{$newVal}=$i + 1;$setTags=$setTagsList{$newVal}[$i]if$setTagsList{$newVal}[$i]}unless (DoSetFromFile($mt,$newVal,$setTags)){$rtnVal=1;next Command}$needSave=1;next}my%opts=(Shift=>0);$opts{Protected}=1 unless$tag =~ /[?*]/;if ($tag =~ s/<// and defined$newVal){if (defined FilenameSPrintf($newVal)){SlurpFile($newVal,\\$newVal)or next}else {$tag =~ s/([-+]|\\xe2\\x88\\x92)$// and $opts{$addDelOpt{$1}}=1;my$result=Image::ExifTool::IsWritable($tag);if ($result){$opts{ProtectSaved}=$saveCount;push@dynamicFiles,[$tag,$newVal,\\%opts ];++$isWriting}elsif (defined$result){Warn \"Tag '${tag}' is not writable\\n\"}else {Warn \"Tag '${tag}' does not exist\\n\"}next}}if ($tag =~ s/([-+]|\\xe2\\x88\\x92)$//){$opts{$addDelOpt{$1}}=1;$newVal='' if $1 eq '-' and not defined$newVal}if ($escapeC and defined$newVal){$newVal =~ s/\\\\(x([0-9a-fA-F]{2})|.)/$2 ? chr(hex($2)) : $unescC{$1} || $1/seg}my ($rtn,$wrn)=$mt->SetNewValue($tag,$newVal,%opts);$needSave=1;++$isWriting if$rtn;$wrn and Warning($mt,$wrn);}unless ($csv){for (@exclude){$mt->SetNewValue($_,undef,Replace=>2);$needSave=1}}unless ($isWriting or $outOpt or @tags){Error \"Nothing to do.\\n\";next}}elsif (grep /^(\\*:)?\\*$/,@exclude){Error \"All tags excluded -- nothing to do.\\n\";next}if ($isWriting){if (defined$diff){Error \"Can't use -diff option when writing tags\\n\";next}elsif ($plot){Error \"Can't use -plot option when writing tags\\n\";next}elsif (@tags and not $outOpt and not $csv){my ($tg,$s)=@tags > 1 ? (\"$tags[0] ...\",'s'): ($tags[0],'');Warn \"Ignored superfluous tag name$s or invalid option$s: -$tg\\n\"}}$mt->SaveNewValues()if$outOpt or (@dynamicFiles and $needSave);$multiFile=1 if@files > 1;@exclude and $mt->Options(Exclude=>\\@exclude);undef$binaryOutput if$html;if ($binaryOutput){$outFormat=99;$mt->Options(PrintConv=>0);unless ($textOut or $binaryStdout){binmode(STDOUT);$binaryStdout=1;$mt->Options(TextOut=>($vout=\\*STDERR))}undef$showGroup}if (defined$showGroup and not (@tags and ($allGroup or $csv))and ($sortOpt or not defined$sortOpt)){$mt->Options(Sort=>\"Group$showGroup\")}if ($textOut){CleanFilename($textOut);$textOut=\".$textOut\" unless$textOut =~ /[.%]/ or defined$tagOut}if ($outOpt){my$type=GetFileType($outOpt);if ($type){my$canWrite=CanWrite($outOpt);unless ($canWrite){if (defined$canWrite and $canWrite eq ''){$type=Image::ExifTool::GetFileExtension($outOpt);$type=uc($outOpt)unless defined$type}Error \"Can't write $type files\\n\";next}$scanWritable=$type unless CanCreate($type)}else {$scanWritable=1}$isWriting=1}elsif ($isWriting or defined$deleteOrig){$scanWritable=1}$altEnc=$mt->Options('Charset');undef$altEnc if$altEnc eq 'UTF8';if (not $altEnc and $mt->Options('Lang')ne 'en'){$fixLen=eval {require Unicode::GCString}? 2 : 1}if (@fileOrder){my@allFiles;ProcessFiles($mt,\\@allFiles);my$sortTool=Image::ExifTool->new;$sortTool->Options(FastScan=>$fileOrderFast)if$fileOrderFast;$sortTool->Options(PrintConv=>$mt->Options('PrintConv'));$sortTool->Options(Duplicates=>0);my (%sortBy,%isFloat,@rev,$file);push@rev,(s/^-// ? 1 : 0)foreach@fileOrder;for$file (@allFiles){my@tags;my$info=$sortTool->ImageInfo(Infile($file,1),@fileOrder,\\@tags);for (@tags){$_=$$info{$_};defined $_ or $_='~',next;$isFloat{$_}=Image::ExifTool::IsFloat($_);s/(\\d+)/(length($1) < 12 ? '0'x(12-length($1)) : '') . $1/eg unless$isFloat{$_}}$sortBy{$file}=\\@tags}@files=sort {my ($i,$cmp);for ($i=0;$i<@rev;++$i){my$u=$sortBy{$a}[$i];my$v=$sortBy{$b}[$i];if (not $isFloat{$u}and not $isFloat{$v}){$cmp=$u cmp $v}elsif ($isFloat{$u}and $isFloat{$v}){$cmp=$u <=> $v}else {$cmp=$isFloat{$u}? -1 : 1}return$rev[$i]? -$cmp : $cmp if$cmp}return$a cmp $b}@allFiles}elsif (defined$progress){my@allFiles;ProcessFiles($mt,\\@allFiles);@files=@allFiles}$progressMax=scalar@files if defined$progress;my@dbKeys=keys%database;if (@dbKeys){if (eval {require Cwd}){undef$evalWarning;local$SIG{'__WARN__'}=sub {$evalWarning=$_[0]};for (@dbKeys){my$db=$database{$_};tr/\\\\/\\// and $database{$_}=$db;my$absPath=AbsPath($_);if (defined$absPath){$database{$absPath}=$db unless$database{$absPath};if ($verbose and $verbose > 1){print$vout \"Imported entry for '${_}' (full path: '${absPath}')\\n\"}}elsif ($verbose and $verbose > 1){print$vout \"Imported entry for '${_}' (no full path)\\n\"}}}}ProcessFiles($mt);Error \"No file with specified extension\\n\" if$filtered and not $validFile;if ($textOut){for (keys%outTrailer){next unless$outTrailer{$_};if ($mt->Open(\\*OUTTRAIL,$_,'>>')){my$fp=\\*OUTTRAIL;print$fp $outTrailer{$_};close$fp}else {Error(\"Error appending to $_\\n\")}}}else {print$sectTrailer if$sectTrailer;print$fileTrailer if$fileTrailer and not $fileHeader;my ($fp,$err);if ($textOut2){if ($mt->Open(\\*OUTFILE,$textOut2,'>')){$fp=\\*OUTFILE}else {Error(\"Error creating $textOut2\\n\");$err=1}}unless ($err){PrintCSV($fp)if$csv and not $isWriting;if ($plot){$plot->Draw($fp || \\*STDOUT);if ($$plot{Error}){Error(\"Error: $$plot{Error}\\n\");$err=1}elsif ($$plot{Warn}){Warn(\"Warning: $$plot{Warn}\\n\")}}}if ($fp){close($fp)or $err=1;if ($err){$mt->Unlink($textOut2)}else {$created{$textOut2}=1}}}my$totWr=$countGoodWr + $countBadWr + $countSameWr + $countCopyWr + $countGoodCr + $countBadCr;if (defined$deleteOrig){unless ($quiet){printf \"%5d directories scanned\\n\",$countDir if$countDir;printf \"%5d directories created\\n\",$countNewDir if$countNewDir;printf \"%5d files failed condition\\n\",$countFailed if$countFailed;printf \"%5d image files found\\n\",$count}if (@delFiles){if ($deleteOrig==1){printf '%5d originals will be deleted! Are you sure [y/n]? ',scalar(@delFiles);my$response=<STDIN>;unless ($response =~ /^(y|yes)\\s*$/i){Warn \"Originals not deleted.\\n\";next}}$countGoodWr=$mt->Unlink(@delFiles);$countBad=scalar(@delFiles)- $countGoodWr}if ($quiet){}elsif ($count and not $countGoodWr and not $countBad){printf \"%5d original files found\\n\",$countGoodWr}elsif ($deleteOrig){printf \"%5d original files deleted\\n\",$countGoodWr if$count;printf \"%5d originals not deleted due to errors\\n\",$countBad if$countBad}else {printf \"%5d image files restored from original\\n\",$countGoodWr if$count;printf \"%5d files not restored due to errors\\n\",$countBad if$countBad}}elsif ((not $binaryStdout or $verbose)and not $quiet){my$tot=$count + $countBad;if ($countDir or $totWr or $countFailed or $tot > 1 or $textOut or %countLink){my$o=(($html or $json or $xml or %printFmt or $csv or $plot)and not $textOut)? \\*STDERR : $vout;printf($o \"%5d directories scanned\\n\",$countDir)if$countDir;printf($o \"%5d directories created\\n\",$countNewDir)if$countNewDir;printf($o \"%5d files failed condition\\n\",$countFailed)if$countFailed;printf($o \"%5d image files created\\n\",$countGoodCr)if$countGoodCr;printf($o \"%5d image files updated\\n\",$countGoodWr)if$totWr - $countGoodCr - $countBadCr - $countCopyWr;printf($o \"%5d image files unchanged\\n\",$countSameWr)if$countSameWr;printf($o \"%5d image files %s\\n\",$countCopyWr,$overwriteOrig ? 'moved' : 'copied')if$countCopyWr;printf($o \"%5d files weren't updated due to errors\\n\",$countBadWr)if$countBadWr;printf($o \"%5d files weren't created due to errors\\n\",$countBadCr)if$countBadCr;printf($o \"%5d image files read\\n\",$count)if ($tot+$countFailed)>1 or ($countDir and not $totWr);printf($o \"%5d files could not be read\\n\",$countBad)if$countBad;printf($o \"%5d output files created\\n\",scalar(keys%created))if$textOut or $textOut2;printf($o \"%5d output files appended\\n\",scalar(keys%appended))if%appended;printf($o \"%5d hard links created\\n\",$countLink{Hard}|| 0)if$countLink{Hard}or $countLink{BadHard};printf($o \"%5d hard links could not be created\\n\",$countLink{BadHard})if$countLink{BadHard};printf($o \"%5d symbolic links created\\n\",$countLink{Sym}|| 0)if$countLink{Sym}or $countLink{BadSym};printf($o \"%5d symbolic links could not be created\\n\",$countLink{BadSym})if$countLink{BadSym}}}if ($countBadWr or $countBadCr or $countBad){$rtnVal=1}elsif ($countFailed and not ($count or $totWr)and not $rtnVal){$rtnVal=2}Cleanup();}close STAYOPEN if$stayOpen >= 2;Exit$rtnValApp;sub GetImageInfo($$) {my ($et,$orig)=@_;my (@foundTags,@found2,$info,$info2,$et2,$file,$file2,$ind,$g8);if (defined$windowTitle){if ($progressCount >= $progressNext){my$prog=$progressMax ? \"$progressCount/$progressMax\" : '0/0';my$title=$windowTitle;my ($num,$denom)=split '/',$prog;my$frac=$num / ($denom || 1);my$n=$title =~ s/%(\\d+)b/%b/ ? $1 : 20;my$bar=int($frac * $n + 0.5);my%lkup=(b=>('I' x $bar).('.' x ($n - $bar)),f=>$orig,p=>int(100 * $frac + 0.5),r=>$prog,'%'=>'%',);$title =~ s/%([%bfpr])/$lkup{$1}/eg;SetWindowTitle($title);if (defined$progressMax){undef$progressNext}else {$progressNext += $progressIncr}}++$progressCount unless defined$progressMax}unless (length$orig or $outOpt){Warn qq(Error: Zero-length file name - \"\"\\n);++$countBad;return}if (@srcFmt){my ($fmt,$first);for$fmt (@srcFmt){$file=$fmt eq '@' ? $orig : FilenameSPrintf($fmt,$orig);$et->Exists($file)and undef($first),last;$verbose and print$vout \"Source file $file does not exist\\n\";$first=$file unless defined$first}$file=$first if defined$first;my ($d,$f)=Image::ExifTool::SplitFileName($orig);$et->Options(UserParam=>\"OriginalDirectory#=$d\");$et->Options(UserParam=>\"OriginalFileName#=$f\")}else {$file=$orig}for$g8 (sort keys%altFile){my$altName=$orig;$altName =~ s/\\$/\\$\\$/g;$altName=FilenameSPrintf($altFile{$g8},$altName);$et->SetAlternateFile($g8,$altName)}my$pipe=$file;if ($doUnzip){if ($file =~ /\\.(gz|bz2)$/i){my$type=lc $1;if ($file =~ /[^-_.'A-Za-z0-9\\/\\\\]/){Warn \"Error: Insecure zip file name. Skipped\\n\";EFile($file);++$countBad;return}if ($type eq 'gz'){$pipe=qq{gzip -dc \"$file\" |}}else {$pipe=qq{bzip2 -dc \"$file\" |}}$$et{TRUST_PIPE}=1}}if (@condition){unless ($file eq '-' or $et->Exists($file)){Warn \"Error: File not found - $file\\n\";EFile($file);FileNotFound($file);++$countBad;return}my$result;unless ($failCondition){undef$evalWarning;local$SIG{'__WARN__'}=sub {$evalWarning=$_[0]};my (%info,$condition);my$opts={Duplicates=>1,RequestTags=>\\@requestTags,Verbose=>0,HtmlDump=>0 };$$opts{FastScan}=$fastCondition if defined$fastCondition;@foundTags=('*',@tags)if@tags;$info=$et->ImageInfo(Infile($pipe,$isWriting),\\@foundTags,$opts);for$condition (@condition){my$cond=$et->InsertTagValues($condition,\\@foundTags,\\%info);{package Image::ExifTool;my$self=$et;$result=eval$cond;$@ and $evalWarning=$@}if ($evalWarning){undef$result;if ($verbose){chomp$evalWarning;$evalWarning =~ s/ at \\(eval .*//s;Warn \"Condition: $evalWarning - $file\\