ExifTool Forum

ExifTool => Newbies => Topic started by: borisros on July 21, 2020, 02:39:07 PM

Title: Compare DateTimeOriginal with the filename Date
Post by: borisros on July 21, 2020, 02:39:07 PM
Hi there,

I am trying to organize my photos library and find my self doing a lot of manual work.
What I am trying to do right now is to compare between DateTimeOriginal from EXIF to the filename, which formatted as following: YYYYMMDD_HHMMSS...).
This could be an easy task if not those small differences (usually up to 1 sec) between the two. I believe it happens due to the fact that the filename and the EXIF are not generated simultaneously.

So my question is as following:
Could somebody help me with the command line, which will compare the EXIF DateTimeOriginal and filename based date and allow mismatch of (let's say) +/- 2 sec. If it fails the check, it should print the filename (key: -filename).

Thank you in advance,
Boris
Title: Re: Compare DateTimeOriginal with the filename Date
Post by: StarGeek on July 21, 2020, 04:59:32 PM
Complicated and messy, but here's an example
exiftool -if "abs(${DateTimeOriginal;$_.='+00:00';DateFmt('%s')}-${filename;s/\D//g;s/(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/$1:$2:$3 $4:$5:$6/;$_=Image::ExifTool::GetUnixTime($_)})>2" -FileName /path/to/files/

Example output

C:\>exiftool -g1 -a -s -DateTimeOriginal Y:\!temp\cccc\2020_03-19-12.54.13.jpg
---- ExifIFD ----
DateTimeOriginal                : 2020:03:19 12:54:13

C:\>exiftool -g1 -a -s -if "abs(${DateTimeOriginal;$_.='+00:00';DateFmt('%s')}-${filename;s/\D//g;s/(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/$1:$2:$3 $4:$5:$6/;$_=Image::ExifTool::GetUnixTime($_)})>2" -filename -DateTimeOriginal Y:\!temp\cccc\2020_03-19-12.54.13.jpg
    1 files failed condition

C:\>exiftool -P -overwrite_original -echo "Adding 3 seconds" -DateTimeOriginal+=0:0:3 Y:\!temp\cccc\2020_03-19-12.54.13.jpg
Adding 3 seconds
    1 image files updated

C:\>exiftool -g1 -a -s -if "abs(${DateTimeOriginal;$_.='+00:00';DateFmt('%s')}-${filename;s/\D//g;s/(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/$1:$2:$3 $4:$5:$6/;$_=Image::ExifTool::GetUnixTime($_)})>2" -filename -DateTimeOriginal Y:\!temp\cccc\2020_03-19-12.54.13.jpg
---- System ----
FileName                        : 2020_03-19-12.54.13.jpg
---- ExifIFD ----
DateTimeOriginal                : 2020:03:19 12:54:16

C:\>exiftool -P -overwrite_original -echo "Subtracting 6 seconds, net -3 seconds from filenaem" -DateTimeOriginal-=0:0:6 Y:\!temp\cccc\2020_03-19-12.54.13.jpg
Subtracting 6 seconds, net -3 seconds from filenaem
    1 image files updated

C:\>exiftool -g1 -a -s -if "abs(${DateTimeOriginal;$_.='+00:00';DateFmt('%s')}-${filename;s/\D//g;s/(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d).*/$1:$2:$3 $4:$5:$6/;$_=Image::ExifTool::GetUnixTime($_)})>2" -filename -DateTimeOriginal Y:\!temp\cccc\2020_03-19-12.54.13.jpg
---- System ----
FileName                        : 2020_03-19-12.54.13.jpg
---- ExifIFD ----
DateTimeOriginal                : 2020:03:19 12:54:10


A cleaner option would be a variation of the user-defined function in this post (https://exiftool.org/forum/index.php?topic=8964.msg46206#msg46206)
print "in config\n";
%Image::ExifTool::UserDefined = (
'Image::ExifTool::Composite' => {
AbsTimeDiff => {
Require => {
0 => 'FileName',
1 => 'DateTimeOriginal',
},
ValueConv => q{
$val[0]=~s/\D//g; # Clear out all non-digits
return undef unless $val[0] =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/; # return if there isn't at least 14 digits
return abs(Image::ExifTool::GetUnixTime($val[1]."+00:00") - Image::ExifTool::GetUnixTime("$1:$2:$3 $4:$5:$6"));
},
},
},
);
1; #end


You could then use
exiftool -if "$AbsTimeDiff>2" -Filename /path/to/files

Example output:
C:\>exiftool -config temp2.config  -g1 -a -s -AbsTimeDiff -DateTimeOriginal -filename Y:\!temp\cccc\2020_03-19-12.54.13.jpg
in config
---- System ----
FileName                        : 2020_03-19-12.54.13.jpg
---- ExifIFD ----
DateTimeOriginal                : 2020:03:19 12:54:13
---- Composite ----
AbsTimeDiff                     : 0

C:\>exiftool -P -overwrite_original -echo "Adding 3 seconds" -DateTimeOriginal+=0:0:3 Y:\!temp\cccc\2020_03-19-12.54.13.jpg
Adding 3 seconds
    1 image files updated

C:\>exiftool -config temp2.config  -g1 -a -s -AbsTimeDiff -DateTimeOriginal -filename Y:\!temp\cccc\2020_03-19-12.54.13.jpg
in config
---- System ----
FileName                        : 2020_03-19-12.54.13.jpg
---- ExifIFD ----
DateTimeOriginal                : 2020:03:19 12:54:16
---- Composite ----
AbsTimeDiff                     : 3

C:\>exiftool -P -overwrite_original -echo "Subtracting 6 seconds, net -3 seconds from filenaem" -DateTimeOriginal-=0:0:6 Y:\!temp\cccc\2020_03-19-12.54.13.jpg
Subtracting 6 seconds, net -3 seconds from filenaem
    1 image files updated

C:\>exiftool -config temp2.config  -g1 -a -s -AbsTimeDiff -DateTimeOriginal -filename Y:\!temp\cccc\2020_03-19-12.54.13.jpg
in config
---- System ----
FileName                        : 2020_03-19-12.54.13.jpg
---- ExifIFD ----
DateTimeOriginal                : 2020:03:19 12:54:10
---- Composite ----
AbsTimeDiff                     : 3
Title: Re: Compare DateTimeOriginal with the filename Date
Post by: borisros on July 22, 2020, 06:54:04 PM
Wow. Such a great solution. Thank you.
I did check only config based, and it works like a charm.
I modified a little bit the code in order to calculate the difference using other sources ('CreateDate' and 'FileCreateDate') if 'DateTimeOriginal' is empty.
Here is the code:

%Image::ExifTool::UserDefined = (
'Image::ExifTool::Composite' => {
AbsTimeDiff => {
Desire => {
0 => 'FileName',
1 => 'FileType',
2 => 'DateTimeOriginal',
3 => 'CreateDate',
4 => 'FileCreateDate',
},
ValueConv => q{
# Clear out all non-digits
$val[0] =~ s/\D//g;
# return if there isn't at least 14 digits
return undef unless $val[0] =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/;
my ($filename_date, $exif_date);
$filename_date = Image::ExifTool::GetUnixTime("$1:$2:$3 $4:$5:$6");
if (length $val[2]){
$exif_date = Image::ExifTool::GetUnixTime($val[2]."+00:00");
} elsif(length $val[3]){
$exif_date = Image::ExifTool::GetUnixTime($val[3]."+00:00");
} elsif(length $val[4]){
$exif_date = Image::ExifTool::GetUnixTime($val[4]);
} else {
return undef;
};
return abs($exif_date - $filename_date);
},
},
},
);


Now I have a few follow up questions:

Thank you,
Boris
Title: Re: Compare DateTimeOriginal with the filename Date
Post by: Phil Harvey on July 22, 2020, 09:30:46 PM
Hi Boris,

The tag name documentation explains your problems with the other date/time tags:

FileCreateDate: On Mac, this tag is extracted only if it or the MacOS group is specifically requested or the RequestAll API option is set to 2 or higher.

MDItemFSCreationDate: extracted if any "MDItem*" tag or the MacOS group is specifically requested, or by setting the MDItemTags API option to 1 or the RequestAll API option to 2 or higher.

- Phil
Title: Re: Compare DateTimeOriginal with the filename Date
Post by: borisros on July 23, 2020, 11:57:13 AM
Hi Phil,

Thank you for your reply.

Adding the following line into the Option section of the Configuration file did the job.
RequestAll => 3
It was a strange situation, since using the command line command worked without requesting the all API.

Regarding my second question, do you have any idea?
What I am interested in getting from running this code is a list of files with information about the time difference and also between which sources of information.
So, I am looking for something like this:
return ( abs($exif_date - $filename_date) , $notes );
Is it possible?
If so, have I could discriminate between both outputs when I call for it from the comment line?

Thank you in advance,
Boris
Title: Re: Compare DateTimeOriginal with the filename Date
Post by: StarGeek on July 24, 2020, 11:37:29 AM
You would either have to save the calculation to a variable if you wanted to use it and let it be interpolated
my $temp=abs($exif_date - $filename_date);
return ("$temp Calculated based on $notes );


Or use the concatenation  operator
return ( abs($exif_date - $filename_date)." Calculated based on $notes");
Title: Re: Compare DateTimeOriginal with the filename Date
Post by: ratounade on October 08, 2022, 01:08:07 PM
Phil,
your work, your tool is GREAT. Congrats and many many thanks !

I have about 50K photos with all names such as "20221008 131201 xxx.jpg"
Then I used this amazing method from this topic below
exiftool -if "abs(${DateTimeOriginal;$_.='+00:00';DateFmt('%s')}-${filename;s/\D//g;s/(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/$1:$2:$3 $4:$5:$6/;$_=Image::ExifTool::GetUnixTime($_)})>2" -FileName -DateTimeOriginal /path/to/files/

It works... but only if the seconds are not "00". Any idea ???
Indeed surprisingly I get for instance :
======== //XX/Shared Pictures/Photo/2004/200402 Naissance Louise/20040213 072300 Louise a 3 heures.jpg
File Name                      : 20040213 072300 Louise a 3 heures.jpg
Date/Time Original              : 2004:02:13 07:23:00
======== //XX/Public/Shared Pictures/Photo/2004/200402 Naissance Louise/20040213 101900 image53.jpg
File Name                      : 20040213 101900 image53.jpg
Date/Time Original              : 2004:02:13 10:19:00

Thank you again

StarGeek Edit: Edited to correct formatting.
Title: Re: Compare DateTimeOriginal with the filename Date
Post by: Phil Harvey on October 08, 2022, 05:17:01 PM
The problem is extra digits in the file name after the time (in this case, "Louise a 3 heures").  Just add an extra ".*" in the pattern match to remove this:

exiftool -if "abs(${DateTimeOriginal;$_.='+00:00';DateFmt('%s')}-${filename;s/\D//g;s/(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d).*/$1:$2:$3 $4:$5:$6/;$_=GetUnixTime($_)})>2" -FileName -DateTimeOriginal /path/to/files/

I've also removed an unnecessary "Image::ExifTool" scope.

- Phil
Title: Re: Compare DateTimeOriginal with the filename Date
Post by: ratounade on October 09, 2022, 03:49:40 AM
Wonderful ! thank you very much !