Error with exiftool (Warning: Can't delete File:FileCreateDate/FileModify)

Started by ferbulous, March 27, 2024, 08:38:51 AM

Previous topic - Next topic

ferbulous

Hi, I'm using exiftool to batch edits the metadata for google takeout photos on windows.
I just have one issue with .HEIC files which are apparently .JPG files, so I use imagemagick to convert them into .JPG and with some help by chatgpt to generate this batch script to update the metadata from the .json files

example:
IMG_5055.HEIC ---> IMG_5055.JPG
IMG_5055.HEIC.json

The batch script would update the .JPG files from the .HEIC.json


@echo off
setlocal enabledelayedexpansion

REM Set the directory containing the .json files and the corresponding image files
set "directory=C:\Users\nurul\Downloads\Compressed\Takeout\Google Photos\test"

REM Change directory to the specified one
cd /d "%directory%"

REM Loop through each .json file in the directory
for %%F in (*.json) do (
    REM Parse the timestamp from the .json file
    for /F "tokens=3 delims=:}" %%T in ('findstr /C:"\"timestamp\":" "%%F"') do (
        REM Convert the timestamp to the desired format (YYYY:MM:DD HH:MM:SS+08:00) using PowerShell
        set "timestamp=%%T"
        set "formatted_timestamp="
        for /f %%i in ('powershell -command "$timestamp = %%T; (Get-Date '1970-01-01').AddSeconds($timestamp).ToString('yyyy:MM:dd HH:mm:ss') + '+08:00'"') do set "formatted_timestamp=%%i"
    )

    REM Extract the filename without extension
    set "filename=%%~nF"
    REM Remove the .HEIC extension
    set "filename=!filename:.HEIC=!"

    REM Update metadata using ExifTool for the corresponding JPG file
    exiftool -DateTimeOriginal="%formatted_timestamp%" -FileCreateDate="%formatted_timestamp%" -FileModifyDate="%formatted_timestamp%" "!filename!.jpg"

)

echo Metadata updated for all corresponding images.

pause

but I keep getting this error


Warning: Can't delete File:FileCreateDate
Warning: Can't delete File:FileModifyDate
    1 image files updated
Is there anything I'm missing here to get it working?

Phil Harvey

I haven't looked at your script to see how this could happen, but you will get this message if the %formatted_timestamp% is empty.

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

StarGeek

Also, you're doing a lot of extra work that exiftool can most likely do in a single command.  Search through these forums for the many Google Takeout posts that are here.

I'm not very good with BAT files, but from my quick check, it looks like you are trying to write the DateTimeOriginal, FileCreateDate, and FileModifyDate tags with the time stamp from the JSON file, while setting the time zone to +08:00.

Just to verify, you are not shifting the time stamps from the json file to account for the time zone difference?  Because when the file was uploaded to google, it was converted from local time to UTC.

Copying the time stamps as written, you could use this single exiftool command
exiftool -ext jpg -d "%s" -TagsFromFile %d%f.json "-FileCreateDate<${PhotoTakenTimeTimestamp}+08:00" "-FileModifyDate<${PhotoTakenTimeTimestamp}+08:00" "-SubSecDateTimeOriginal<${PhotoTakenTimeTimestamp}+08:00" /path/to/files/

The -d "%s" (-dateFormat "%s") option lets exiftool know that the time stamp will be in Unix time, and exiftool will be able to convert it automatically.

-TagsFromFile %d%f.json tells exiftool that for every JPEG file, it needs to look for a file in the same directory %d and the same base filename, but with a .json extension %f.json in which to copy the data from.

PhotoTakenTimeTimestamp is the exiftool name for the correct time stamp in the JSON file. You can find this name by running the command in FAQ #3 directly on the JSON file.

The -ext (-extension) option is used to process only the jpeg files and not any other filetype.

I used SubSecDateTimeOriginal instead of DateTimeOriginal because it will write to both the DateTimeOriginal tag and the OffsetTimeOriginal tag at the same time.  OffsetTimeOriginal is the location where time zones are written in EXIF.

Finally, I think a better solution would be to copy the data directly from the HEIC file instead of the JSON file, as those should better reflect the actual time, not the time converted to UTC as in the JSON file.  Your command for that would be
exiftool -ext jpg -TagsFromFile %d%f.heic -SubSecDateTimeOriginal "-FileModifyDate<SubSecDateTimeOriginal" "-SubSecDateTimeOriginal<SubSecDateTimeOriginal" /path/to/files/
"It didn't work" isn't helpful. What was the exact command used and the output.
Read FAQ #3 and use that cmd
Please use the Code button for exiftool output

Please include your OS/Exiftool version/filetype

ferbulous

Quote from: Phil Harvey on March 27, 2024, 09:21:34 AMI haven't looked at your script to see how this could happen, but you will get this message if the %formatted_timestamp% is empty.

- Phil

That's correct, i missed the part where it needs to check the timestamp for phototakentime in the json

Quote from: StarGeek on March 27, 2024, 11:16:23 AMAlso, you're doing a lot of extra work that exiftool can most likely do in a single command.  Search through these forums for the many Google Takeout posts that are here.

I'm not very good with BAT files, but from my quick check, it looks like you are trying to write the DateTimeOriginal, FileCreateDate, and FileModifyDate tags with the time stamp from the JSON file, while setting the time zone to +08:00.

Just to verify, you are not shifting the time stamps from the json file to account for the time zone difference?  Because when the file was uploaded to google, it was converted from local time to UTC.

Copying the time stamps as written, you could use this single exiftool command
exiftool -ext jpg -d "%s" -TagsFromFile %d%f.json "-FileCreateDate<${PhotoTakenTimeTimestamp}+08:00" "-FileModifyDate<${PhotoTakenTimeTimestamp}+08:00" "-SubSecDateTimeOriginal<${PhotoTakenTimeTimestamp}+08:00" /path/to/files/

The -d "%s" (-dateFormat "%s") option lets exiftool know that the time stamp will be in Unix time, and exiftool will be able to convert it automatically.

-TagsFromFile %d%f.json tells exiftool that for every JPEG file, it needs to look for a file in the same directory %d and the same base filename, but with a .json extension %f.json in which to copy the data from.

PhotoTakenTimeTimestamp is the exiftool name for the correct time stamp in the JSON file. You can find this name by running the command in FAQ #3 directly on the JSON file.

The -ext (-extension) option is used to process only the jpeg files and not any other filetype.

I used SubSecDateTimeOriginal instead of DateTimeOriginal because it will write to both the DateTimeOriginal tag and the OffsetTimeOriginal tag at the same time.  OffsetTimeOriginal is the location where time zones are written in EXIF.

Finally, I think a better solution would be to copy the data directly from the HEIC file instead of the JSON file, as those should better reflect the actual time, not the time converted to UTC as in the JSON file.  Your command for that would be
exiftool -ext jpg -TagsFromFile %d%f.heic -SubSecDateTimeOriginal "-FileModifyDate<SubSecDateTimeOriginal" "-SubSecDateTimeOriginal<SubSecDateTimeOriginal" /path/to/files/

Thanks for the detailed and examples, i don't quite understand EXIF yet.
Looks like I could just skip the script entirely, I wasn't sure if I needed to add the +8:00 for my timezone.

Also, could I append the changes directly to .jpg files without generating _original files? Or is that how it usually works?

Phil Harvey

A new file is always generated, but if you add -overwrite_original the old file is deleted afterwards instead of renaming it to *_original.

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

StarGeek

QuoteI wasn't sure if I needed to add the +8:00 for my timezone.

It depends upon you.  Like I said, Google converted any local time from the files to UTC, which means in the case of a +08:00 time zone, it subtracted 8 hours.  If it's close enough for you, then no worries.

If you want to adjust it, it's easy for the file system time stamps.  You can the time zone in the above commands to +00:00.

For the DateTimeOriginal tag, you have to manually add the time. You would use this, which adds 8 hours * 60 minutes * 60 seconds to get the number of seconds to subtract
"-SubSecDateTimeOriginal<${PhotoTakenTimeTimestamp;$_+=(8*60*60)}+08:00"

Quote from: ferbulous on March 29, 2024, 03:19:14 AMAlso, could I append the changes directly to .jpg files without generating _original files? Or is that how it usually works?

From the Documention
QuoteBy default the original files are preserved with _original appended to their names -- be sure to verify that the new files are OK before erasing the originals.

You can suppress the creation of backup files with the -overwrite_original option.

My final bit of advice.  Check your files before doing anything to see if you actually have to copy data.  In my experience, having tested Google many times over the years, it does not remove the original data from the files. The only thing that changes is the two file system time stamps, as they are part of the file system and not embedded in the file. Run this command to see if the original time stamps exist
exiftool -time:all -G1 -a -s /path/to/files/
"It didn't work" isn't helpful. What was the exact command used and the output.
Read FAQ #3 and use that cmd
Please use the Code button for exiftool output

Please include your OS/Exiftool version/filetype

ferbulous

Quote from: Phil Harvey on March 29, 2024, 10:59:07 AMA new file is always generated, but if you add -overwrite_original the old file is deleted afterwards instead of renaming it to *_original.

- Phil

Quote from: StarGeek on March 29, 2024, 11:13:09 AM
QuoteI wasn't sure if I needed to add the +8:00 for my timezone.

It depends upon you.  Like I said, Google converted any local time from the files to UTC, which means in the case of a +08:00 time zone, it subtracted 8 hours.  If it's close enough for you, then no worries.

If you want to adjust it, it's easy for the file system time stamps.  You can the time zone in the above commands to +00:00.

For the DateTimeOriginal tag, you have to manually add the time. You would use this, which adds 8 hours * 60 minutes * 60 seconds to get the number of seconds to subtract
"-SubSecDateTimeOriginal<${PhotoTakenTimeTimestamp;$_+=(8*60*60)}+08:00"

Quote from: ferbulous on March 29, 2024, 03:19:14 AMAlso, could I append the changes directly to .jpg files without generating _original files? Or is that how it usually works?

From the Documention
QuoteBy default the original files are preserved with _original appended to their names -- be sure to verify that the new files are OK before erasing the originals.

You can suppress the creation of backup files with the -overwrite_original option.

My final bit of advice.  Check your files before doing anything to see if you actually have to copy data.  In my experience, having tested Google many times over the years, it does not remove the original data from the files. The only thing that changes is the two file system time stamps, as they are part of the file system and not embedded in the file. Run this command to see if the original time stamps exist
exiftool -time:all -G1 -a -s /path/to/files/

Thanks for the advice
I just have 1 more issue with google takeout, i have these duplicated filename but they're indeed different pictures because of how ios seems to reuse the numbering sequence for the photos app.

For example

IMG_2681.HEIC
IMG_2681.HEIC.json
IMG_2681(1).HEIC
IMG_2681.HEIC(1).json

how can edit the command so it would still pick up the (1) in the filename?

exiftool -ext heic -TagsFromFile %d%f.heic(1).json

Phil Harvey

You could do this:

exiftool -ext heic -tagsfromfile "%d%8f.HEIC(1).json" ...

The %8f takes the first 8 characters of the file name.

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

StarGeek

I believe the command in this post will rename JSON file so that the "(#)" is in the correct location.
"It didn't work" isn't helpful. What was the exact command used and the output.
Read FAQ #3 and use that cmd
Please use the Code button for exiftool output

Please include your OS/Exiftool version/filetype

ferbulous

Quote from: Phil Harvey on March 31, 2024, 09:54:59 AMYou could do this:

exiftool -ext heic -tagsfromfile "%d%8f.HEIC(1).json" ...

The %8f takes the first 8 characters of the file name.

- Phil

Thanks, this does work however I'll need to move the duplicated filename to a different folder otherwise the original filename gets updated with the wrong .json file

I'm thinking of making batch script that simply assigns the correct json file based on the duplicated filename.
Am I using the command correctly if I just need to obtain the tag from a single .json file? I'm just getting no writable tags set

exiftool.exe -overwrite_original -d "%%s" -TagsFromFile IMG_2681.HEIC(1).json "-FileCreateDate<${PhotoTakenTimeTimestamp}" "-FileModifyDate<${PhotoTakenTimeTimestamp}" "-SubSecDateTimeOriginal<${PhotoTakenTimeTimestamp}" IMG_2681(1).MP4
Warning: No writable tags set from IMG_2681.HEIC(1).json

Quote from: StarGeek on March 31, 2024, 01:31:30 PMI believe the command in this post will rename JSON file so that the "(#)" is in the correct location.

Thanks, that's another way to do it way by just renaming the .json files