modify filename based on filename

Started by davidcpreston, February 23, 2025, 06:49:20 AM

Previous topic - Next topic

davidcpreston

Windows 11 batch file. Exiftool 13.19
I've looked at lots of examples, but can't work this out, though I imagine it would be easy:-
A typical video file from my drone is "DJI_20241230134847_0001_D.mp4".
If I save a frame using Windows Photos it would by default be named "DJI_20241230134847_0001_D - frame at 2m11s.jpg". At the moment when I save it I a manually change the filename by adding the frame offset and removing the suffix, resulting in "DJI_20241230135058_0001_D.jpg", or even just "DJI_20241230135058.jpg". The videos are only 3 minutes long, so not too difficult to calculate BUT evidently easy to make a typo, so how do I this be done automatically, ideally in one command, please?

The next stage is to update the Create Date from the filename, so they all appear in chronological order on my computer and online photo sites.
Update: I have discovered I can update CreateDate using -CreateDate+="0h2m11s", so if I can work out how to substitute this for the end of the filename it would work. though I may have to do another pass of files that end with that format?

wywh

If the filename datetime from DJI .mp4 is correct (i.e. the time zone is correct) and you do not need frame offset and you don't mind two commands, then this seems to work for the .jpg Windows Photos has exported from that .mp4 (replace my Mac single quotes for Windows double quotes and fine-tune, if needed):

ls -al                                                                                                   
DJI_20241230134847_0001_D - frame at 2m11s.jpg

exiftool -m -overwrite_original -ext jpg -ext heic -ext png -ext webp -ext avif '-AllDates<FileName' '-FileCreateDate<FileName' '-FileModifyDate<FileName' .

exiftool -m -P -fileOrder5 FileName '-FileName<ExifIFD:DateTimeOriginal' -d '%Y-%m%d-%H%M-%S%%+2nc.%%e' .

ls -al
2024-1230-1348-47.jpg

davidcpreston

Thanks, I'm already doing something like that, but I want to add the minutes and seconds at the end of the datetime part of the filename OR to the CreateDate  Tag, which I can update the filename from.
I know I can use "=+0h2m11s" BUT it's how to construct the command from "frame at 2m11s" at the end of the filename

StarGeek

To clarify, you want to take the time stamp from the filename, and then shift it by the numbers after "frame at". This is not a simple task. I had to step away for a bit while creating it to clear my head.

Technically, it probably can be done in two commands. But that would be messy and confusing, so I'll show you how to do it in three commands. Personally, I would probably do it in four steps to make it easier to understand.

Step one, copy the time stamp from the filename into the files. This sets a base time that can be shifted to the correct time in the second step. This is straight up copied from @wywh. I suggest you read up on the other options they provide to decide if you want them or not.
exiftool "-AllDates<FileName" "-FileCreateDate<FileName" "-FileModifyDate<FileName" /path/to/files/

Step two, extract the shift data and shift the time stamps. This is the part which I would split into two commands for sanity's sake. I would shift only one tag and then run a second command to copy that shifted time to all the other tags.
exiftool "-AllDates<${DateTimeOriginal;my $MyShift=$self->GetValue('FileName');$MyShift=~s/.*frame at (\d+)m(\d+)s.*/0:$1:$2/;ShiftTime($MyShift)}" "-FileModifyDate<${FileModifyDate;my $MyShift=$self->GetValue('FileName');$MyShift=~s/.*frame at (\d+)m(\d+)s.*/0:$1:$2/;ShiftTime($MyShift)}" "-FileCreateDate<${FileCreateDate;my $MyShift=$self->GetValue('FileName');$MyShift=~s/.*frame at (\d+)m(\d+)s.*/0:$1:$2/;ShiftTime($MyShift)}" /path/to/files/

Step three, do the final rename, again taken from @wywh. I removed the -P (-preserve) option because renaming a file should not change the FileModifyDate. The -m (-ignoreMinorErrors) option also does nothing for a rename command.
exiftool -fileOrder5 FileName "-FileName<DateTimeOriginal" -d "%Y-%m%d-%H%M-%S%%+2nc.%%e" /path/to/files/

Example output of the first two commands
C:\>exiftool -time:all -G1 -a -s "Y:\!temp\x\y\DJI_20241230134847_0001_D - frame at 2m11s.jpg"
[System]        FileModifyDate                  : 2024:12:30 13:48:47-08:00
[System]        FileAccessDate                  : 2024:12:30 13:48:47-08:00
[System]        FileCreateDate                  : 2024:12:30 13:48:47-08:00
[IFD0]          ModifyDate                      : 2024:12:30 13:48:47
[ExifIFD]       DateTimeOriginal                : 2024:12:30 13:48:47
[ExifIFD]       CreateDate                      : 2024:12:30 13:48:47

C:\>exiftool "-AllDates<${DateTimeOriginal;my $MyShift=$self->GetValue('FileName');$MyShift=~s/.*frame at (\d+)m(\d+)s.*/0:$1:$2/;ShiftTime($MyShift)}" "-FileModifyDate<${FileModifyDate;my $MyShift=$self->GetValue('FileName');$MyShift=~s/.*frame at (\d+)m(\d+)s.*/0:$1:$2/;ShiftTime($MyShift)}" "-FileCreateDate<${FileCreateDate;my $MyShift=$self->GetValue('FileName');$MyShift=~s/.*frame at (\d+)m(\d+)s.*/0:$1:$2/;ShiftTime($MyShift)}" "Y:\!temp\x\y\DJI_20241230134847_0001_D - frame at 2m11s.jpg"
    1 image files updated

C:\>exiftool -time:all -G1 -a -s "Y:\!temp\x\y\DJI_20241230134847_0001_D - frame at 2m11s.jpg"
[System]        FileModifyDate                  : 2024:12:30 13:50:58-08:00
[System]        FileAccessDate                  : 2024:12:30 13:50:58-08:00
[System]        FileCreateDate                  : 2024:12:30 13:50:58-08:00
[IFD0]          ModifyDate                      : 2024:12:30 13:50:58
[ExifIFD]       DateTimeOriginal                : 2024:12:30 13:50:58
[ExifIFD]       CreateDate                      : 2024:12:30 13:50:58
"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

davidcpreston

You're a star, many many thanks for your time.
As described in my previous post, I:-
1. Update CreateDate from all files based on the filename, with any files from my cameras failing as they are not date based, but that's fine.
2. Update all filenames from CreateDate using a consistent date based format.
3. Manually move them into subject named folders and add that to the filename.

So all I have to do is add another step after 1 that processes all files containing "frame at" to add the frame offset to CreateDate using =+ h:m:s. It was just the syntax for getting the h:m:s from filename I couldn't work out, which you have provided in "$MyShift=$self->GetValue('FileName');$MyShift=~s/.*frame at (\d+)m(\d+)s.*/0:$1:$2/;ShiftTime($MyShift)}""

davidcpreston

#5
The final solution. Thank you so much for your patience.


@echo off
rem Put all files in C:\Pending - Update CreateDate Tag from filename then rename files based on datetime
rem  so they can easily be moved into sub folders based on subject.
rem Rename files in subfolders based on CreateDate tag and subject from folder name

C:
cd \pending

rem If no files in root folder process sub folders
rem if exist *.* or any variant of is still true if no files except directories exist, so workaround is:-
for /f "delims=" %%a in ('dir /b /a-d') do set filesonly=%%a
rem setlocal enableDelayedExpansion
if "%filesonly%" == "" goto renamefilesinfolders

rem Save files
Copy *.* C:\Saved

rem Update CreatDate tag from filename
"D:\Documents\Utilities\exiftool\exiftool.exe" -m -overwrite_original "-CreateDate<filename" *.*

rem Add frame offset to CreateDate for files with "frame at"
if not exist "*frame at*.*" goto renamefiles
"D:\Documents\Utilities\exiftool\exiftool.exe" -overwrite_original "-CreateDate<${CreateDate;my $MyShift=$self->GetValue('FileName');$MyShift=~s/.*frame at (\d+)m(\d+)s.*/0:$1:$2/;ShiftTime($MyShift)}" "*frame at*.*"

rem Rename file based on CreateDate
:renamefiles
"D:\Documents\Utilities\exiftool\exiftool.exe" "-filename<CreateDate" -d "%%Y-%%m-%%d_%%H-%%M-%%S%%%%+c.%%%%e" *.*
goto end

rem Rename files based on CreateDate tag and folder name (subject)
:renamefilesinfolders
"D:\Documents\Utilities\exiftool\exiftool.exe" -r -fileorder CreateDate "-filename<CreateDate" -d "%%Y-%%m-%%d_%%H-%%M-%%S%%%%+c %%%%-1:D.%%%%e" "c:\pending"

:end