News:

2023-03-15 Major improvements to the new Geolocation feature

Main Menu

Add date and time to Exif Info of scanned jpg photos

Started by PAPPL, December 20, 2015, 10:32:29 AM

Previous topic - Next topic

PAPPL

I've scanned a ton of old paper photos and named them like this:

1977 Grandpa at the sea.jpg
1981-07 Holiday in greece.jpg
1984-12-24 Christmas with family.jpg
...

As you can see, i didn't get the month and day for every old photo.
To add exif information to these scans for automatic chronological sorting in certain apps, i figured out how to use this great Exiftool by searching FAQ and forum, but i need a little help with an additional if command.

What's working (Terminal OSX= ' instead "):

1. If only year is known then:
exiftool '-exif:datetimeoriginal<${filename;/(\d{4})/ ? $_=qq($1:01:01 00:00:00) : undef}' -overwrite_original -r DIR

2. If year and month is known then:
exiftool '-exif:datetimeoriginal<${filename;/(\d{4}).(\d{2})/ ? $_=qq($1:$2:01 00:00:00) : undef}' -overwrite_original -r DIR

3. If year, month and day is known then:
exiftool '-exif:datetimeoriginal<${filename;/(\d{4}).(\d{2}).(\d{2})/ ? $_=qq($1:$2:$3 00:00:00) : undef}' -overwrite_original -r DIR

If i set option 2 or 3 for all jpgs i get "Warning: No writable tags set..." when day or month/day missing in filename. If i set option 1 for all jpgs i get only year in exif info.

How can i add an if-command to check the filename (month/day available or not) and then decide which code (1, 2 or 3) to apply to the jpg file?

Please help,

Thanks a lot

Pappl

Phil Harvey

Hi Pappi,

This starts to get a bit messy to do this with the advanced formatting feature (it is probably better to create a user-defined Composite tag for this), but here goes:

'${filename;my @a=(/\d+/g);$a[1] or $a[1]="01";$a[2] or $a[2]="01";$_="$a[0]:$a[1]:$a[2] 00:00:00"}'

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

PAPPL

Hi,



I don't understand the logic of the advanced feature. I've tried to merge my code with yours by trial and error, but no success. Even the documentation doesn't help, because my brain sees only $ and other strange code instead of logic.

:(
Thanks for your help!

Pappl

Phil Harvey

Hi Pappi,

The command should be:

exiftool '-exif:datetimeoriginal<${filename;my @a=(/\d+/g);$a[1] or $a[1]="01";$a[2] or $a[2]="01";$_="$a[0]:$a[1]:$a[2] 00:00:00"}' -overwrite_original -r DIR

And it should handle all 3 of your filename cases.

The strange code requires some knowledge of Perl to understand what is going on.  The ExifTool documentation doesn't attempt to teach Perl.

To break it down:

my @a=(/\d+/g); - @a is an array initialized from all numbers in the FileName string

$a[1] or $a[1]="01"; - set element 1 of the array to "01" if not defined

$a[2] or $a[2]="01"; - set element 2 of the array to "02" if not defined

$_="$a[0]:$a[1]:$a[2] 00:00:00" - set the tag value to the string using the first 3 elements of the @a array

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

PAPPL

Hi Phil,

thanks so much!

Tried your code and it is working for these filenames:
1977 Grandpa at the sea.jpg
1981-07 Holiday in greece.jpg
1984-12-24 Christmas with family.jpg


Found it's not working if filenames are:

1977 Grandpa at the sea 10.jpg
1977 Grandpa at the sea 11.jpg


or

1981-07 Holiday in greece 01.jpg
1981-07 Holiday in greece 02.jpg
1981-07 Holiday in greece 03.jpg


Then it will add the file numbering to the exif date, e.g.:
03.07.1981 (greece) or 01.11.1977 (grandpa)


Your explanation helped me to create a variation with your OR statements and my old code which avoids file numbering beeing added to the exif date.

exiftool '-alldates<${filename;/(\d{4}).(\d{2}).(\d{2})/ ? $_=qq($1:$2:$3 00:00:00) : undef or /(\d{4}).(\d{2})/ ? $_=qq($1:$2:01 00:00:00) : undef or /(\d{4})/ ? $_=qq($1:01:01 00:00:00) : undef}' -r -overwrite_original -if '(not $dateTimeOriginal)' DIR
(Working in OSX, use " instead of ' for Windows)

Added an if-statement to ignore all photos, which already contain exif-date, to avoid overwriting exif-tags and only aim at jpgs without exif-information.
It also skips files, which are missing numbers at the beginning, like P0003789.jpg:)

So i'm very happy now to have a working solution for my scanned paper-photos and having many jpg's batch exified now!  ;D

The only problem i didn't catch is:
If the filename is
"19840408 Birthdayparty 03.jpg" instead of "1984-04-08 Birthdayparty 03.jpg" i get very weird dates set in exif-information, like 1984.40.8.  ???
I had to remove the wrong exif data with:
exiftool -all= -overwrite_original -r DIR

To make it perfect, there must be a way to add another IF-statement to only attack files without a number in 5th filename-position from beginning, or rename files manually.  :-[

Thank you,

PAPPL

Phil Harvey

Hi Pappl,

Try this:

exiftool '-alldates<${filename;/^(\d{4})[^\d]?(\d{2})[^\d]?(\d{2})/ ? $_=qq($1:$2:$3 00:00:00) : undef or /^(\d{4})[^\d]?(\d{2})/ ? $_=qq($1:$2:01 00:00:00) : undef or /^(\d{4})/ ? $_=qq($1:01:01 00:00:00) : undef}' -r -overwrite_original -if '(not $dateTimeOriginal)' DIR

This is even more messy, but it will only match dates at the start of the file, and makes the date separator optional.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

PAPPL

Hi Phil,

it works!



        Filename                              Writes Exif-Date(s) dd.mm.yyyy
1977 Description 02.jpg          ->          01.01.1977
1977-Description 03.jpg          ->          01.01.1977
1978-07 Description 02.jpg      ->          01.07.1978
197807 Description 02.jpg       ->          01.07.1978
197807-Description 03.jpg       ->          01.07.1978
1980-02-23 Description 04.jpg ->          23.02.1980
1980-02-23-Description 05.jpg ->          23.02.1980
19800223 Description 06.jpg   ->          23.02.1980

:D

Here's the working All-in-One Exif-Information sulution for old paper photo scans to add as much information as possible with one command:
(Replace green with your personal information)

exiftool '-alldates<${filename;/^(\d{4})[^\d]?(\d{2})[^\d]?(\d{2})/ ? $_=qq($1:$2:$3 00:00:00) : undef or /^(\d{4})[^\d]?(\d{2})/ ? $_=qq($1:$2:01 00:00:00) : undef or /^(\d{4})/ ? $_=qq($1:01:01 00:00:00) : undef}' -Exif:Artist="CUSTOM PHOTOGRAPHER/FAMILY NAME" "-ExifImageWidth<ImageWidth" "-ExifImageHeight<ImageHeight" "-make=CAMERA/SCANNER MANUFACTURER NAME" "-model=CAMERA/SCANNER MODEL NAME" -GPSLongitudeRef=E or W -GPSLongitude=xx,yyyyy (= Coordinates Longitude) -GPSLatitudeRef=S or N -GPSLatitude=xx,yyyyy (=Coordinates Latitude) -GPSAltitudeRef='Above Sea Level' -GPSAltitude=200 '-Exif:XPSubject<${filename;s/\.jpg$//i}' '-ImageDescription<${filename;s/\.jpg$//i}' -Description='GENERAL DESCRIPTION OF PHOTOS' '-Comment<${filename;s/\.jpg$//i}' '-usercomment<${filename;s/\.jpg$//i}' '-Exif:XPComment<${filename;s/\.jpg$//i}' -keywords='SHORT COMMENT' '-IPTC:Caption-Abstract<${filename;s/\.jpg$//i}' '-IPTC:Headline<${filename;s/\.jpg$//i}' '-IPTC:Keywords<${filename;s/\.jpg$//i}' '-XMP:Subject<${filename;s/\.jpg$//i}' -overwrite_original -r -if '(not $dateTimeOriginal)' DIR

(Working with OSX, replace ' with " for Windows)

Thanks Phil, i'm very happy now to have all photo scans finalized before christmas.

-PAPPL

deb27

Just ran across this post which is almost exactly what I was looking for.

Quote from: Phil Harvey on December 21, 2015, 03:37:36 PM
...

The command should be:

exiftool '-exif:datetimeoriginal<${filename;my @a=(/\d+/g);$a[1] or $a[1]="01";$a[2] or $a[2]="01";$_="$a[0]:$a[1]:$a[2] 00:00:00"}' -overwrite_original -r DIR

And it should handle all 3 of your filename cases.
...
In my case the file names are in the form:

1988-03-007.jpg  where 1988-03 is the year and the month but the -007 is a sequence number.
So I really only need a portion of the recommended command. I don't care about the day portion.

I'm on windows and tried the following command:
exiftool "-exif:datetimeoriginal<${filename;my @a=(/\d+/g);$a[1] or $a[1]="01";$_="$a[0]:$a[1]:01 00:00:00"}" -overwrite_original *.jpg
with the intent of just setting the day to 01. However it didn't work. I got the following errors.  Unfortunately I don't know Perl so it's probably a silly syntax error:
exiftool "-exif:datetimeoriginal<${filename;my @a=(/\d+/g);$a[1] or $a[1]="01";$_="$a[0]:$a[1]:01 00:00:00"}" -overwrite_original *.jpg
Warning: Error opening file - 00:00:00}
Error: File not found - 00:00:00}
Warning: [minor] Tag 'a' not defined - 1989-12-000.jpg
Warning: No writable tags set from 1989-12-000.jpg
Warning: [minor] Tag 'a' not defined - 1989-12-001.jpg
Warning: No writable tags set from 1989-12-001.jpg
...


Hayo Baan

The problem is that the original command was written for a UNIX/MAC system where single quotes can (and must) be used to enclose the whole string. On windows you have to use double quotes, but that causes the inner double quotes to get mixed up. You can not simply change all inner quotes to single quotes though as that would prevent the $a stuff to be correctly interpolated. Luckily Perl is flexible about the quotes you use, so we can fix this easily:
exiftool "-exif:datetimeoriginal<${filename;my @a=(/\d+/g);$a[1] or $a[1]='01';$_=qq($a[0]:$a[1]:01 00:00:00)}" -overwrite_original *.jpg
This should work for you (the qq(...) puts "quotes" around the stuff inside it) :)
Hayo Baan – Photography
Web: www.hayobaan.nl

deb27

Beautiful!  Thank you so very much for your solution and your fast response!

rosspeters

I have one other (simpler) file naming convention I was hoping to get help with. I have named files based on "YYYYMMDD - Description" and would like to copy the date info in to Exif info on the files.

An example filename would be:

20140627 - Last day of school.jpg

I have looked at the examples in the post (and a few other) but cannot seem to get the syntax right. These are a mixture of scanned photos plus others where the Exif seems to have been lost.

One more comment - I would be using on Windows, so double quote marks!

Thanks in advance!

Phil Harvey

Try this:

exiftool "-filename<$datetimeoriginal - $description.%e" -d %Y%m%d DIR

This assumes that the information you mention is in the EXIF DateTimeOriginal and XMP Description tags.  See FAQ 2 if you need help finding the tag names.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

rosspeters

Thanks for the quick reply. I tried this but got the following error (as an example)

Warning: [minor] Tag 'datetimeoriginal' not defined - Test/20070617 - Father's Day.jpg
Warning: No writable tags set from Test/20070617 - Father's Day.jpg

When you say "This assumes that the information you mention is in the EXIF DateTimeOriginal and XMP Description tags.  See FAQ 2 if you need help finding the tag names." I am not sure I follow - I am looking to take the date from the filename and populate the tags as I don't think the info is there.

Sorry if I am dense on this - I am a EXIF super newbie!



Phil Harvey

Sorry.  My fault for reading too quickly.  I assumed you were trying to set the file name.

To set the EXIF date/time from the file name, do this:

exiftool "-datetimeoriginal<${filename} 00:00:00" DIR

The "00:00:00" sets the time to all zeros if it doesn't appear in the file name.  Note that other numbers that exist in the file name after the date may find their way into the time.

This command sets the DateTimeOriginal tag.  To set all 3 common EXIF date/time tags, use "AllDates" instead of "DateTimeOriginal".

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).