Added options -Y, -O and -D to the exiv2 tool to adjust Exif timestamps by years, months and days.

This commit is contained in:
Andreas Huggel 2007-12-22 17:51:55 +00:00
parent 4db769885f
commit 7a8bf1dad8
6 changed files with 220 additions and 82 deletions

View File

@ -100,12 +100,12 @@ namespace {
// returns 0 if successful
int str2Tm(const std::string& timeStr, struct tm* tm);
// Convert a string "YYYY:MM:DD HH:MI:SS" to a UTC time, -1 on error
time_t str2Time(const std::string& timeStr);
// Convert a UTC time to a string "YYYY:MM:DD HH:MI:SS", "" on error
std::string time2Str(time_t time);
// Convert a tm structure to a string "YYYY:MM:DD HH:MI:SS", "" on error
std::string tm2Str(struct tm* tm);
/*!
@brief Copy metadata from source to target according to Params::copyXyz
@ -1428,7 +1428,10 @@ namespace Action {
int Adjust::run(const std::string& path)
try {
adjustment_ = Params::instance().adjustment_;
adjustment_ = Params::instance().adjustment_;
yearAdjustment_ = Params::instance().yodAdjust_[Params::yodYear].adjustment_;
monthAdjustment_ = Params::instance().yodAdjust_[Params::yodMonth].adjustment_;
dayAdjustment_ = Params::instance().yodAdjust_[Params::yodDay].adjustment_;
if (!Exiv2::fileExists(path, true)) {
std::cerr << path
@ -1491,21 +1494,69 @@ namespace Action {
<< ek << "' " << _("not set\n");
return 1;
}
time_t time = str2Time(timeStr);
if (time == (time_t)-1) {
std::cerr << path << ": " << _("Failed to parse or convert timestamp") << " `"
if (Params::instance().verbose_) {
bool comma = false;
std::cout << _("Adjusting") << " `" << ek << "' " << _("by");
if (yearAdjustment_ != 0) {
std::cout << (yearAdjustment_ < 0 ? " " : " +") << yearAdjustment_ << " ";
if (yearAdjustment_ < -1 || yearAdjustment_ > 1) {
std::cout << _("years");
}
else {
std::cout << _("year");
}
comma = true;
}
if (monthAdjustment_ != 0) {
if (comma) std::cout << ",";
std::cout << (monthAdjustment_ < 0 ? " " : " +") << monthAdjustment_ << " ";
if (monthAdjustment_ < -1 || monthAdjustment_ > 1) {
std::cout << _("months");
}
else {
std::cout << _("month");
}
comma = true;
}
if (dayAdjustment_ != 0) {
if (comma) std::cout << ",";
std::cout << (dayAdjustment_ < 0 ? " " : " +") << dayAdjustment_ << " ";
if (dayAdjustment_ < -1 || dayAdjustment_ > 1) {
std::cout << _("days");
}
else {
std::cout << _("day");
}
comma = true;
}
if (adjustment_ != 0) {
if (comma) std::cout << ",";
std::cout << " " << adjustment_ << _("s");
}
}
struct tm tm;
if (str2Tm(timeStr, &tm) != 0) {
if (Params::instance().verbose_) std::cout << std::endl;
std::cerr << path << ": " << _("Failed to parse timestamp") << " `"
<< timeStr << "'\n";
return 1;
}
if (Params::instance().verbose_) {
std::cout << _("Adjusting") << " `" << ek << "' " << _("by")
<< (adjustment_ < 0 ? " " : " +")
<< adjustment_ << _(" s to ");
const long monOverflow = (tm.tm_mon + monthAdjustment_) / 12;
tm.tm_mon = (tm.tm_mon + monthAdjustment_) % 12;
tm.tm_year += yearAdjustment_ + monOverflow;
// Let's not create files with non-4-digit years, we can't read them.
if (tm.tm_year > 9999 - 1900 || tm.tm_year < 1000 - 1900) {
if (Params::instance().verbose_) std::cout << std::endl;
std::cerr << path << ": " << _("Can't adjust timestamp by") << " "
<< yearAdjustment_ + monOverflow
<< " " << _("years") << "\n";
return 1;
}
time += adjustment_;
time_t time = timegm(&tm);
time += adjustment_ + dayAdjustment_ * 86400;
timeStr = time2Str(time);
if (Params::instance().verbose_) {
std::cout << timeStr << std::endl;
std::cout << " " << _("to") << " " << timeStr << std::endl;
}
md->setValue(timeStr);
return 0;
@ -1659,17 +1710,14 @@ namespace {
return 0;
} // str2Tm
time_t str2Time(const std::string& timeStr)
{
struct tm tm;
if (str2Tm(timeStr, &tm) != 0) return (time_t)-1;
time_t t = timegm(&tm);
return t;
}
std::string time2Str(time_t time)
{
struct tm* tm = gmtime(&time);
return tm2Str(tm);
} // time2Str
std::string tm2Str(struct tm* tm)
{
if (0 == tm) return "";
std::ostringstream os;
@ -1682,7 +1730,7 @@ namespace {
<< std::setw(2) << tm->tm_sec;
return os.str();
} // time2Str
} // tm2Str
int metacopy(const std::string& source,
const std::string& target,

View File

@ -218,6 +218,10 @@ namespace Action {
const std::string& path) const;
long adjustment_;
long yearAdjustment_;
long monthAdjustment_;
long dayAdjustment_;
}; // class Adjust
/*!

View File

@ -3,7 +3,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH EXIV2 1 "December 12th, 2007"
.TH EXIV2 1 "December 23rd, 2007"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@ -57,8 +57,9 @@ different formats. Modification commands can be applied on-the-fly.
Delete image metadata from the files.
.TP
.B ad | adjust
Adjust Exif timestamps by the given time. Requires option \fB\-a\fP
\fItime\fP.
Adjust Exif timestamps by the given time. Requires at least one of the
options \fB\-a\fP \fItime\fP, \fB\-Y\fP \fIyrs\fP, \fB\-O\fP
\fImon\fP or \fB\-D\fP \fIday\fP.
.TP
.B mo | modify
Apply commands to modify (add, set, delete) the Exif, IPTC and XMP
@ -122,6 +123,18 @@ Time adjustment in the format [\-]HH[:MM[:SS]]. This option is only
used with the 'adjust' action. Examples: 1 adds one hour, 1:01
adds one hour and one minute, \-0:00:30 subtracts 30 seconds.
.TP
.B \-Y \fIyrs\fP
Time adjustment by a positive or negative number of years, for
the 'adjust' action.
.TP
.B \-O \fImon\fP
Time adjustment by a positive or negative number of months, for
the 'adjust' action.
.TP
.B \-D \fIday\fP
Time adjustment by a positive or negative number of days, for
the 'adjust' action.
.TP
.B \-p \fImode\fP
Print mode for the 'print' action. Possible modes are:
.br

View File

@ -165,6 +165,12 @@ int main(int argc, char* const argv[])
// class Params
Params* Params::instance_ = 0;
const Params::YodAdjust Params::emptyYodAdjust_[] = {
{ false, "-Y", 0 },
{ false, "-O", 0 },
{ false, "-D", 0 },
};
Params& Params::instance()
{
if (0 == instance_) {
@ -211,8 +217,8 @@ void Params::help(std::ostream& os) const
{
usage(os);
os << _("\nActions:\n")
<< _(" ad | adjust Adjust Exif timestamps by the given time. This\n"
" action requires the option -a time.\n")
<< _(" ad | adjust Adjust Exif timestamps by the given time. This action\n"
" requires at least one of the -a, -Y, -O or -D options.\n")
<< _(" pr | print Print image metadata.\n")
<< _(" rm | delete Delete image metadata from the files.\n")
<< _(" in | insert Insert metadata from corresponding *.exv files.\n"
@ -240,6 +246,9 @@ void Params::help(std::ostream& os) const
<< _(" -F Do not prompt before renaming files (Force).\n")
<< _(" -a time Time adjustment in the format [-]HH[:MM[:SS]]. This option\n"
" is only used with the 'adjust' action.\n")
<< _(" -Y yrs Year adjustment with the 'adjust' action.\n")
<< _(" -O mon Month adjustment with the 'adjust' action.\n")
<< _(" -D day Day adjustment with the 'adjust' action.\n")
<< _(" -p mode Print mode for the 'print' action. Possible modes are:\n")
<< _(" s : print a summary of the Exif metadata (the default)\n")
<< _(" t : interpreted (translated) Exif data (shortcut for -Pkyct)\n")
@ -307,6 +316,9 @@ int Params::option(int opt, const std::string& optarg, int optopt)
case 't': rc = evalRename(opt, optarg); break;
case 'T': rc = evalRename(opt, optarg); break;
case 'a': rc = evalAdjust(optarg); break;
case 'Y': rc = evalYodAdjust(yodYear, optarg); break;
case 'O': rc = evalYodAdjust(yodMonth, optarg); break;
case 'D': rc = evalYodAdjust(yodDay, optarg); break;
case 'p': rc = evalPrint(optarg); break;
case 'P': rc = evalPrintCols(optarg); break;
case 'd': rc = evalDelete(optarg); break;
@ -377,6 +389,12 @@ int Params::evalAdjust(const std::string& optarg)
int rc = 0;
switch (action_) {
case Action::none:
case Action::adjust:
if (adjust_) {
std::cerr << progname()
<< ": " << _("Ignoring surplus option -a") << " " << optarg << "\n";
break;
}
action_ = Action::adjust;
adjust_ = parseTime(optarg, adjustment_);
if (!adjust_) {
@ -385,10 +403,6 @@ int Params::evalAdjust(const std::string& optarg)
rc = 1;
}
break;
case Action::adjust:
std::cerr << progname()
<< ": " << _("Ignoring surplus option -a") << " " << optarg << "\n";
break;
default:
std::cerr << progname()
<< ": " << _("Option -a is not compatible with a previous option\n");
@ -398,6 +412,38 @@ int Params::evalAdjust(const std::string& optarg)
return rc;
} // Params::evalAdjust
int Params::evalYodAdjust(const Yod& yod, const std::string& optarg)
{
int rc = 0;
switch (action_) {
case Action::none: // fall-through
case Action::adjust:
if (yodAdjust_[yod].flag_) {
std::cerr << progname()
<< ": " << _("Ignoring surplus option") << " "
<< yodAdjust_[yod].option_ << " " << optarg << "\n";
break;
}
action_ = Action::adjust;
yodAdjust_[yod].flag_ = true;
if (!Util::strtol(optarg.c_str(), yodAdjust_[yod].adjustment_)) {
std::cerr << progname() << ": " << _("Error parsing") << " "
<< yodAdjust_[yod].option_ << " "
<< _("option argument") << " `" << optarg << "'\n";
rc = 1;
}
break;
default:
std::cerr << progname()
<< ": " << _("Option") << " "
<< yodAdjust_[yod].option_ << " "
<< _("is not compatible with a previous option\n");
rc = 1;
break;
}
return rc;
} // Params::evalYodAdjust
int Params::evalPrint(const std::string& optarg)
{
int rc = 0;
@ -683,9 +729,13 @@ int Params::getopt(int argc, char* const argv[])
std::cerr << progname() << ": " << _("An action must be specified\n");
rc = 1;
}
if (action_ == Action::adjust && !adjust_) {
if ( action_ == Action::adjust
&& !adjust_
&& !yodAdjust_[yodYear].flag_
&& !yodAdjust_[yodMonth].flag_
&& !yodAdjust_[yodDay].flag_) {
std::cerr << progname() << ": "
<< _("Adjust action requires option -a time\n");
<< _("Adjust action requires at least one -a, -Y, -O or -D option\n");
rc = 1;
}
if ( action_ == Action::modify

View File

@ -145,6 +145,16 @@ public:
//! Enumerates the policies to handle existing files in rename action
enum FileExistsPolicy { overwritePolicy, renamePolicy, askPolicy };
//! Enumerates year, month and day adjustments.
enum Yod { yodYear, yodMonth, yodDay };
//! Structure for year, month and day adjustment command line arguments.
struct YodAdjust {
bool flag_; //!< Adjustment flag.
const char* option_; //!< Adjustment option string.
long adjustment_; //!< Adjustment value.
};
bool help_; //!< Help option flag.
bool version_; //!< Version option flag.
bool verbose_; //!< Verbose (talkative) option flag.
@ -163,6 +173,7 @@ public:
int target_; //!< What common target to process.
long adjustment_; //!< Adjustment in seconds.
YodAdjust yodAdjust_[3]; //!< Year, month and day adjustment info.
std::string format_; //!< Filename format (-r option arg).
bool formatSet_; //!< Whether the format is set with -r
CmdFiles cmdFiles_; //!< Names of the modification command files
@ -173,12 +184,20 @@ public:
std::string suffix_; //!< File extension of the file to insert
Files files_; //!< List of non-option arguments.
private:
//! Pointer to the global Params object.
static Params* instance_;
//! Initializer for year, month and day adjustment info.
static const YodAdjust emptyYodAdjust_[];
bool first_;
private:
/*!
@brief Default constructor. Note that optstring_ is initialized here.
The c'tor is private to force instantiation through instance().
*/
Params() : optstring_(":hVvfbuktTFa:r:p:P:d:e:i:c:m:M:l:S:"),
Params() : optstring_(":hVvfbuktTFa:Y:O:D:r:p:P:d:e:i:c:m:M:l:S:"),
help_(false),
version_(false),
verbose_(false),
@ -197,7 +216,12 @@ private:
adjustment_(0),
format_("%Y%m%d_%H%M%S"),
formatSet_(false),
first_(true) {}
first_(true)
{
yodAdjust_[yodYear] = emptyYodAdjust_[yodYear];
yodAdjust_[yodMonth] = emptyYodAdjust_[yodMonth];
yodAdjust_[yodDay] = emptyYodAdjust_[yodDay];
}
//! Prevent copy-construction: not implemented.
Params(const Params& rhs);
@ -206,6 +230,7 @@ private:
//@{
int evalRename(int opt, const std::string& optarg);
int evalAdjust(const std::string& optarg);
int evalYodAdjust(const Yod& yod, const std::string& optarg);
int evalPrint(const std::string& optarg);
int evalPrintCols(const std::string& optarg);
int evalDelete(const std::string& optarg);
@ -214,11 +239,6 @@ private:
int evalModify(int opt, const std::string& optarg);
//@}
//! Pointer to the global Params object.
static Params* instance_;
bool first_;
public:
/*!
@brief Call Getopt::getopt() with optstring, to inititate command line

View File

@ -27,8 +27,8 @@ Usage: exiv2 [ options ] [ action ] file ...
Manipulate the Exif metadata of images.
Actions:
ad | adjust Adjust Exif timestamps by the given time. This
action requires the option -a time.
ad | adjust Adjust Exif timestamps by the given time. This action
requires at least one of the -a, -Y, -O or -D options.
pr | print Print image metadata.
rm | delete Delete image metadata from the files.
in | insert Insert metadata from corresponding *.exv files.
@ -57,6 +57,9 @@ Options:
-F Do not prompt before renaming files (Force).
-a time Time adjustment in the format [-]HH[:MM[:SS]]. This option
is only used with the 'adjust' action.
-Y yrs Year adjustment with the 'adjust' action.
-O mon Month adjustment with the 'adjust' action.
-D day Day adjustment with the 'adjust' action.
-p mode Print mode for the 'print' action. Possible modes are:
s : print a summary of the Exif metadata (the default)
t : interpreted (translated) Exif data (shortcut for -Pkyct)
@ -111,60 +114,60 @@ Adjust -------------------------------------------------------------------
File 1/15: exiv2-empty.jpg
exiv2-empty.jpg: No Exif data found in the file
File 2/15: exiv2-canon-powershot-s40.jpg
Adjusting `Exif.Image.DateTime' by -43261 s to 2003:12:14 00:00:43
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2003:12:14 00:00:43
Adjusting `Exif.Photo.DateTimeDigitized' by -43261 s to 2003:12:14 00:00:43
Adjusting `Exif.Image.DateTime' by -43261s to 2003:12:14 00:00:43
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2003:12:14 00:00:43
Adjusting `Exif.Photo.DateTimeDigitized' by -43261s to 2003:12:14 00:00:43
File 3/15: exiv2-nikon-e990.jpg
Adjusting `Exif.Image.DateTime' by -43261 s to 2000:05:06 02:05:44
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2000:05:06 02:05:44
Adjusting `Exif.Photo.DateTimeDigitized' by -43261 s to 2000:05:06 02:05:44
Adjusting `Exif.Image.DateTime' by -43261s to 2000:05:06 02:05:44
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2000:05:06 02:05:44
Adjusting `Exif.Photo.DateTimeDigitized' by -43261s to 2000:05:06 02:05:44
File 4/15: exiv2-nikon-d70.jpg
Adjusting `Exif.Image.DateTime' by -43261 s to 2004:03:29 22:42:45
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2004:03:29 22:42:45
Adjusting `Exif.Photo.DateTimeDigitized' by -43261 s to 2004:03:29 22:42:45
Adjusting `Exif.Image.DateTime' by -43261s to 2004:03:29 22:42:45
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2004:03:29 22:42:45
Adjusting `Exif.Photo.DateTimeDigitized' by -43261s to 2004:03:29 22:42:45
File 5/15: exiv2-nikon-e950.jpg
Adjusting `Exif.Image.DateTime' by -43261 s to 2001:04:05 23:50:39
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2001:04:05 23:50:39
Adjusting `Exif.Photo.DateTimeDigitized' by -43261 s to 2001:04:05 23:50:39
Adjusting `Exif.Image.DateTime' by -43261s to 2001:04:05 23:50:39
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2001:04:05 23:50:39
Adjusting `Exif.Photo.DateTimeDigitized' by -43261s to 2001:04:05 23:50:39
File 6/15: exiv2-canon-eos-300d.jpg
Adjusting `Exif.Image.DateTime' by -43261 s to 2003:09:25 20:18:50
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2003:09:25 20:18:50
Adjusting `Exif.Photo.DateTimeDigitized' by -43261 s to 2003:09:25 20:18:50
Adjusting `Exif.Image.DateTime' by -43261s to 2003:09:25 20:18:50
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2003:09:25 20:18:50
Adjusting `Exif.Photo.DateTimeDigitized' by -43261s to 2003:09:25 20:18:50
File 7/15: exiv2-kodak-dc210.jpg
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2000:10:26 04:45:50
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2000:10:26 04:45:50
File 8/15: exiv2-fujifilm-finepix-s2pro.jpg
Adjusting `Exif.Image.DateTime' by -43261 s to 2003:09:26 11:15:35
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2003:09:26 11:15:35
Adjusting `Exif.Photo.DateTimeDigitized' by -43261 s to 2003:09:26 11:15:35
Adjusting `Exif.Image.DateTime' by -43261s to 2003:09:26 11:15:35
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2003:09:26 11:15:35
Adjusting `Exif.Photo.DateTimeDigitized' by -43261s to 2003:09:26 11:15:35
File 9/15: exiv2-sigma-d10.jpg
Adjusting `Exif.Image.DateTime' by -43261 s to 2004:03:18 11:39:25
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2004:03:16 07:51:37
Adjusting `Exif.Photo.DateTimeDigitized' by -43261 s to 2004:03:18 11:39:25
Adjusting `Exif.Image.DateTime' by -43261s to 2004:03:18 11:39:25
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2004:03:16 07:51:37
Adjusting `Exif.Photo.DateTimeDigitized' by -43261s to 2004:03:18 11:39:25
File 10/15: exiv2-olympus-c8080wz.jpg
Adjusting `Exif.Image.DateTime' by -43261 s to 2004:02:08 09:37:44
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2004:02:08 09:37:44
Adjusting `Exif.Photo.DateTimeDigitized' by -43261 s to 2004:02:08 09:37:44
Adjusting `Exif.Image.DateTime' by -43261s to 2004:02:08 09:37:44
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2004:02:08 09:37:44
Adjusting `Exif.Photo.DateTimeDigitized' by -43261s to 2004:02:08 09:37:44
File 11/15: exiv2-panasonic-dmc-fz5.jpg
Adjusting `Exif.Image.DateTime' by -43261 s to 2005:02:18 21:20:16
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2005:02:18 21:20:16
Adjusting `Exif.Photo.DateTimeDigitized' by -43261 s to 2005:02:18 21:20:16
Adjusting `Exif.Image.DateTime' by -43261s to 2005:02:18 21:20:16
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2005:02:18 21:20:16
Adjusting `Exif.Photo.DateTimeDigitized' by -43261s to 2005:02:18 21:20:16
File 12/15: exiv2-sony-dsc-w7.jpg
Adjusting `Exif.Image.DateTime' by -43261 s to 2005:05:27 05:18:33
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2005:05:27 05:18:33
Adjusting `Exif.Photo.DateTimeDigitized' by -43261 s to 2005:05:27 05:18:33
Adjusting `Exif.Image.DateTime' by -43261s to 2005:05:27 05:18:33
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2005:05:27 05:18:33
Adjusting `Exif.Photo.DateTimeDigitized' by -43261s to 2005:05:27 05:18:33
File 13/15: exiv2-canon-eos-20d.jpg
Warning: Makernote: Pointer to next IFD is out of bounds; ignored.
Adjusting `Exif.Image.DateTime' by -43261 s to 2006:08:02 09:52:00
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2006:08:02 09:52:00
Adjusting `Exif.Photo.DateTimeDigitized' by -43261 s to 2006:08:02 09:52:00
Adjusting `Exif.Image.DateTime' by -43261s to 2006:08:02 09:52:00
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2006:08:02 09:52:00
Adjusting `Exif.Photo.DateTimeDigitized' by -43261s to 2006:08:02 09:52:00
File 14/15: exiv2-canon-eos-d30.jpg
Adjusting `Exif.Image.DateTime' by -43261 s to 2000:10:04 01:54:04
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2000:10:04 01:54:04
Adjusting `Exif.Photo.DateTimeDigitized' by -43261 s to 2000:10:04 01:54:04
Adjusting `Exif.Image.DateTime' by -43261s to 2000:10:04 01:54:04
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2000:10:04 01:54:04
Adjusting `Exif.Photo.DateTimeDigitized' by -43261s to 2000:10:04 01:54:04
File 15/15: exiv2-canon-powershot-a520.jpg
Adjusting `Exif.Image.DateTime' by -43261 s to 2006:01:27 22:50:27
Adjusting `Exif.Photo.DateTimeOriginal' by -43261 s to 2006:01:27 22:50:27
Adjusting `Exif.Photo.DateTimeDigitized' by -43261 s to 2006:01:27 22:50:27
Adjusting `Exif.Image.DateTime' by -43261s to 2006:01:27 22:50:27
Adjusting `Exif.Photo.DateTimeOriginal' by -43261s to 2006:01:27 22:50:27
Adjusting `Exif.Photo.DateTimeDigitized' by -43261s to 2006:01:27 22:50:27
Rename -------------------------------------------------------------------
File 1/15: exiv2-empty.jpg