Compare DateTimeOriginal with the filename Date

Started by borisros, July 21, 2020, 02:39:07 PM

Previous topic - Next topic

borisros

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

StarGeek

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
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
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

borisros

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:

  • I get nothing from 'FileCreateDate' in config, but with the command line, it works as expected. I also tried the 'MDItemFSCreationDate', since I'm running it on Mac. But without success.
  • Is it possible to return not only the difference value, but also some text comment, like: "Calculated based on..."? In order to use it as an output of the command line.

Thank you,
Boris

Phil Harvey

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
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

borisros

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

StarGeek

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");
* Did you read FAQ #3 and use the command listed there?
* Please use the Code button for exiftool code/output.
 
* Please include your OS, Exiftool version, and type of file you're processing (MP4, JPG, etc).

ratounade

#6
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.

Phil Harvey

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
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

ratounade