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
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
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
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
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
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");
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.
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
Wonderful ! thank you very much !