Can I rename files with both the UTC time and local time in one command?

Started by delerious, April 13, 2023, 04:30:16 AM

Previous topic - Next topic

delerious

I came up with the following command that renames files using the local timestamp, camera model, and original filename.

exiftool -progress -d "%Y-%m-%d_%H-%M-%S" "-filename<${CreateDate} (${Model;}) - %f%-1c.%e" "-filecreatedate#<CreateDate#" "-filemodifydate#<CreateDate#" -r .
Now I'd like to include the UTC timestamp (at the beginning) and the SubSecTimeDigitized value in the filename as well. So the filename would look like:

Quote2023-04-11_23-12-00-239__2023-04-11_19-12-00-239 (iPhone SE) - IMG_2384.JPG

I'm sure I can run one command to get the OffsetTimeDigitized value, calculate the UTC time, and then run a second command to actually do the renaming, and then repeat for every file. But is what I want possible to do in one command for all the files recursively?

StarGeek

I'm pretty sure that there's an exiftool function that could replace some of this, but I couldn't find it atm.

As long as you have OffsetTimeDigitized correctly embedded in the file, then you could use this as the tag for UTC.  At least I think POSIX is built into exiftool.
${SubSecCreateDate#;use POSIX qw(strftime);DateFmt('%s');$_=strftime('%Y-%m-%d_%H-%M-%S',gmtime($_))}

To include that with the rename and add the subseconds,
"-filename<${SubSecCreateDate#;use POSIX qw(strftime);DateFmt('%s');$_=strftime('%Y-%m-%d_%H-%M-%S',gmtime($_))}.${SubSecTimeDigitized}_${CreateDate}.${SubSecTimeDigitized} (${Model;}) - %f%-1c.%e"

Example
C:\>exiftool -time:all --system:all -model -G1 -a -s y:\!temp\Test4.jpg
[ExifIFD]       CreateDate                      : 2023:04:13 12:00:00
[ExifIFD]       OffsetTimeDigitized             : -07:00
[ExifIFD]       SubSecTimeDigitized             : 111
[Composite]     SubSecCreateDate                : 2023:04:13 12:00:00.111-07:00
[IFD0]          Model                           : iPhone SE

C:\>exiftool -d "%Y-%m-%d_%H-%M-%S" "-Testname<${SubSecCreateDate#;use POSIX qw(strftime);DateFmt('%s');$_=strftime('%Y-%m-%d_%H-%M-%S',gmtime($_))}.${SubSecTimeDigitized}_${CreateDate}.${SubSecTimeDigitized} (${Model;}) - %f%-1c.%e" y:\!temp\Test4.jpg
'y:/!temp/Test4.jpg' --> 'y:/!temp/2023-04-13_19-00-00.111_2023-04-13_12-00-00.111 (iPhone SE) - Test4.jpg'
    0 image files updated
    1 image files unchanged
* 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).

delerious

Thank you for that command! Would it also be possible to set the system timestamps (filecreatedate and filemodifydate) to the UTC time in the same command?

StarGeek

You cannot set the system time stamps to UTC.  They will always display the adjusted local time.  The only way to change that is to set the computer time zone to UTC. (stray though, can you set it to UTC? or is it set to the time zone UK uses...  Quick check, yes you can set it to UTC)

You can test this by trying to set it to a local time with a time zone, then the UTC time with a +00:00 time zone. 

Example, setting to the same time locally for me, UTC and then +07:00 time zone.  All return the same result
C:\>exiftool -FileModifyDate="2023:04:16 12:00:00-07:00" y:\!temp\Test4.jpg
    1 image files updated

C:\>exiftool -G1 -a -s -FileModifyDate y:\!temp\Test4.jpg
[System]        FileModifyDate                  : 2023:04:16 12:00:00-07:00

C:\>exiftool -FileModifyDate="2023:04:16 19:00:00-00:00" y:\!temp\Test4.jpg
    1 image files updated

C:\>exiftool -G1 -a -s -FileModifyDate y:\!temp\Test4.jpg
[System]        FileModifyDate                  : 2023:04:16 12:00:00-07:00

C:\>exiftool -FileModifyDate="2023:04:17 02:00:00+07:00" y:\!temp\Test4.jpg
    1 image files updated

C:\>exiftool -G1 -a -s -FileModifyDate y:\!temp\Test4.jpg
[System]        FileModifyDate                  : 2023:04:16 12:00:00-07:00
* 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).

delerious

Thanks. It is interesting because I read that NTFS stores all timestamps in UTC: https://superuser.com/questions/109922/are-windows-file-timestamps-timezone-aware

But I guess it's always converted to the local time of the PC you're on when you look at the timestamp in Windows Explorer or when some application like ExifTool queries for it. That means any attempt to get the system create/modify timestamps to show the local time of the time zone you were in when you took the photo, or to show UTC time, is a futile attempt, and you're better off saving whatever timestamp you want in the filename.

StarGeek

Quote from: delerious on April 17, 2023, 02:46:24 AMBut I guess it's always converted to the local time of the PC you're on when you look at the timestamp in Windows Explorer or when some application like ExifTool queries for it.

Yes, I believe the third paragraph in that answer attempts to explain this.

QuoteThat means any attempt to get the system create/modify timestamps to show the local time of the time zone you were in when you took the photo, or to show UTC time, is a futile attempt, and you're better off saving whatever timestamp you want in the filename.

The embedded time stamps are the best thing to look at.  If you're looking at the file through Windows, you would look at the "Date Taken" for images or "Media Created" for videos.  Or use a Digital Asset Management (DAM) program such as Lightroom or DigiKam which will give much more control of the files and their metadata.

* 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).

delerious

Just out of curiosity though, would it be possible to take a timestamp generated for the filename and use it later in the command to set the filecreatedate or filemodifydate without having to duplicate code?

StarGeek

Not really.  For the most part, you can't really set a tag and then use that tag to set another in the same command.  There are some things you can do with the -UserParam option or by creating a shortcut tag, but they are really just a variation of setting each tag to the same value in the first place.
* 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).

delerious

So I'm noticing a problem when I try to rename a file AND set the system create/modify timestamps all in one command.

For example, when I issue these commands to change the filename and set the create/modify timestamps:

G:\Documents>exiftool -s -SubSecCreateDate sunset.jpg
SubSecCreateDate                : 2023:02:12 17:30:37.359-08:00

G:\Documents>exiftool -progress -d "%Y-%m-%d_%H-%M-%S" "-filename<${SubSecCreateDate#;use POSIX qw(strftime);DateFmt('%s');$_=strftime('%Y-%m-%d_%H-%M-%S',gmtime($_))}.${SubSecTimeDigitized}_${CreateDate}.${SubSecTimeDigitized} (${Model;}) - %f%-1c.%e" "-filecreatedate<SubSecCreateDate#" "-filemodifydate<SubSecCreateDate#" sunset.jpg
======== sunset.jpg [1/1]
'sunset.jpg' --> '2023-02-13_01-30-37.359_2023-02-12_17-30-37.359 (iPhone 14 Pro) - sunset.jpg'
    1 image files updated

G:\Documents>exiftool -s -File*Date "2023-02-13_01-30-37.359_2023-02-12_17-30-37.359 (iPhone 14 Pro) - sunset.jpg"
FileModifyDate                  : 2023:02:12 17:30:37-05:00
FileAccessDate                  : 2023:02:12 17:30:37-05:00
FileCreateDate                  : 2023:02:12 17:30:37-05:00

At this point, I would have expected the FileModifyDate/FileCreateDate to be 2023:02:12 20:30:37-05:00 (my PC is in the Eastern time zone). Maybe the fact that I put -d "%Y-%m-%d_%H-%M-%S" in the command caused the FileModifyDate/FileCreateDate to be 2023:02:12 17:30:37-05:00 instead? But I read that putting the hash (#) at the end of the tag name would tell ExifTool to use the original unformatted value, so I made sure to specify -filecreatedate<SubSecCreateDate# and -filemodifydate<SubSecCreateDate#.

Then after I ran the following command without the renaming portion, the system file create/modify timestamps were set correctly:

G:\Documents>exiftool -progress "-filecreatedate<SubSecCreateDate#" "-filemodifydate<SubSecCreateDate#" "2023-02-13_01-30-37.359_2023-02-12_17-30-37.359 (iPhone 14 Pro) - sunset.jpg"
======== 2023-02-13_01-30-37.359_2023-02-12_17-30-37.359 (iPhone 14 Pro) - sunset.jpg [1/1]
    1 image files updated

G:\Documents>exiftool -s -File*Date "2023-02-13_01-30-37.359_2023-02-12_17-30-37.359 (iPhone 14 Pro) - sunset.jpg"
FileModifyDate                  : 2023:02:12 20:30:37-05:00
FileAccessDate                  : 2023:02:12 20:30:37-05:00
FileCreateDate                  : 2023:02:12 20:30:37-05:00

Any idea why the first command with the renaming and the setting of the system timestamps didn't set the timestamps correctly?

Phil Harvey

I'll have to look into this, but I suspect your advanced formatting expression may be changing the value of an internal ExifTool variable.

- 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 ($).

Phil Harvey

No.  That wasn't the problem.  The problem is with the -d option as you suspected.  The inverse date/time formatting also applies, so you have to also disable this in the destination tags with a "#":

exiftool -progress -d "%Y-%m-%d_%H-%M-%S" "-filename<${SubSecCreateDate#;use POSIX qw(strftime);DateFmt('%s');$_=strftime('%Y-%m-%d_%H-%M-%S',gmtime($_))}.${SubSecTimeDigitized}_${CreateDate}.${SubSecTimeDigitized} (${Model;}) - %f%-1c.%e" "-filecreatedate#<SubSecCreateDate#" "-filemodifydate#<SubSecCreateDate#" sunset.jpg

- 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 ($).

delerious

Thanks Phil, that worked! So when you say "inverse", that means writing to tags as opposed to reading, and since the filecreatedate/filemodifydate didn't have a # after them, the -d option was causing the time zone offset to be dropped?

Phil Harvey

Yes.  The -d option may be used to reformat input date/time values when writing.  For example:

> exiftool a.jpg -datetimeoriginal=1537655580 -d %s
    1 image files updated
> exiftool a.jpg -datetimeoriginal
Date/Time Original              : 2018:09:22 18:33: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 ($).

delerious

#13
A follow-up question:

Would it be possible to have exiftool output some tags along with a computed value? For example, how would I have it output the CreateDate tag as well as the UTC time with subseconds, which from the posts above was computed by doing
${SubSecCreateDate#;use POSIX qw(strftime);DateFmt('%s');$_=strftime('%Y-%m-%d_%H-%M-%S',gmtime($_))}.${SubSecTimeDigitized}

I know how to output the CreateDate tag, but I'm not sure how to output the UTC time with subseconds on a subsequent line (maybe as a fake tag or something).

Phil Harvey

The two ways to do calculations are in the advanced formatting expression using and using the -p option output, or by creating a user-defined tag (which works with any output format).

- 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 ($).