set all to oldest known date

Started by Andreas999, January 12, 2017, 08:42:46 PM

Previous topic - Next topic

djcroustibat

I'm sorry. You're right. Thank You. Stupid mistake.

So I tried the command and now the tag was created well, but it seems lost the UTC value :

Command :

exiftool -time:all -s /path/to/photo/IMG.jpg

got :

FileModifyDate                  : 2021:06:20 12:55:08+02:00
FileAccessDate                  : 2022:02:04 18:31:05+01:00
FileInodeChangeDate             : 2022:02:04 11:58:44+01:00

Run oldest_datetime_config  :
Command :

exiftool -config /path/to/oldest_datetime_config "-DateTimeOriginal<OldestDateTime" "/path/to/photo/IMG.jpg"

got :
    1 image files updated

Command :

exiftool -time:all -s /path/to/photo/IMG.jpg

got :

FileModifyDate                  : 2022:02:04 18:33:59+01:00
FileAccessDate                  : 2022:02:04 18:34:00+01:00
FileInodeChangeDate             : 2022:02:04 18:33:59+01:00
DateTimeOriginal                : 2021:06:20 12:55:08

The "+02:00" disappeared

How can I solve this ?

Thanks

StarGeek

You can't.  The DateTimeOriginal cannot contain a time zone.

You can write to SubSecDateTimeOriginal and that will save the date/time in DateTimeOriginal and the time zone in OffsetTimeOriginal, which is the EXIF tag that holds time zones.  You can also write to XMP:DateCreated, which is the XMP equivalent of the EXIF:DateTimeOriginal and can hold a time zone.  Best solution would be to write both
exiftool -config /path/to/oldest_datetime_config "-SubSecDateTimeOriginal<OldestDateTime" "-XMP:DateCreated<OldestDateTime" "/path/to/photo/IMG.jpg"
"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

djcroustibat

Ah ok. Thank You. So I will use this command you suggested.

One more thing : In this thread Phil told to use the -d parameter and add a line :


Add this line to the tag definition for using OldestDateTime with the -d option:

Code: [Select]
            PrintConv => '$self->ConvertDateTime($val)',

Where goes this line in the script and how add the -d parameter to the command line you suggested me ?

Thank You.

djcroustibat

I think I found the answer myself.
I just modified the function like this :


%Image::ExifTool::UserDefined = (
    'Image::ExifTool::Composite' => {
        # Select oldest date from a number of date tags
        OldestDateTime => {
            Desire => {
                0 => 'FileModifyDate',
                1 => 'MDItemFSContentChangeDate',
                2 => 'FileCreateDate',
                3 => 'MDItemFSCreationDate',
                4 => 'ModifyDate',
                5 => 'CreateDate',
                6 => 'DateTimeCreated',
                7 => 'DateTimeOriginal',
            },
            ValueConv => q{
                my $oldest = undef;
                for my $date ($self->ConvertDateTime(@val)) {
                    next if not defined $date or $date lt '1970:01:02';
                    # $date =~ s/[+-]\d{2}:\d{2}$//; # Strip TimeZone
                    if ($date && (!$oldest || $date lt $oldest)) {
                        $oldest = $date;
                    }
                }
                return $oldest;
            },
        },
    },
);

1;


And now when I execute the command :

exiftool -config /path/to/oldest_datetime_config "-SubSecDateTimeOriginal<OldestDateTime" "-XMP:DateCreated<OldestDateTime" "/path/to/photo/IMG.jpg"

I got :

FileModifyDate                  : 2022:02:04 19:55:55+01:00
FileAccessDate                  : 2022:02:04 19:55:57+01:00
FileInodeChangeDate             : 2022:02:04 19:55:55+01:00
DateTimeOriginal                : 2021:06:20 12:55:08
OffsetTimeOriginal              : +02:00
DateCreated                     : 2021:06:20 12:55:08+02:00
SubSecDateTimeOriginal          : 2021:06:20 12:55:08+02:00


So I think it's okay like this for me.
Maybe using the -d parameter is even better.
In the function, I just commented the regex to keep the timezone in the $date variable and get well formated datetime with $self->ConvertDateTime(@val) instead of just @val.

Thank You guys.

Phil Harvey

The PrintConv line should go in the config file after the closing brace of the ValueConv definition.  But this is only useful if you want to format the dates using the -d option, which you aren't doing.  So don't worry about this.  What you have done with ConvertDateTime is wrong, and will break the config file so only FileModifyDate is used.

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

djcroustibat

Okay, So if I rollback the config file, how can I modify it to get what I tried to do : preserve time zone to get -SubSecDateTimeOriginal and -XMP:DateCreated updated without loosing time zone information ?

Thanks.

Phil Harvey

It should work fine with the original config file with the line to strip out the time zone removed.   Your original command lost the time zone because you were writing DateTimeOriginal instead of SubSecDateTimeOriginal.

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

djcroustibat

Yep that's what I finally did, added PrintConv as mentioned and commented time zone strip.

And yes, with SubSecDateTimeOriginal it's okay.

Thank You.

Corrected config maybe it will help someone :

%Image::ExifTool::UserDefined = (
    'Image::ExifTool::Composite' => {
        # Select oldest date from a number of date tags
        OldestDateTime => {
            Desire => {
                0 => 'FileModifyDate',
                1 => 'MDItemFSContentChangeDate',
                2 => 'FileCreateDate',
                3 => 'MDItemFSCreationDate',
                4 => 'ModifyDate',
                5 => 'CreateDate',
                6 => 'DateTimeCreated',
                7 => 'DateTimeOriginal',
            },
            ValueConv => q{
                my $oldest = undef;
                for my $date (@val) {
                    next if not defined $date or $date lt '1970:01:02';
                    #$date =~ s/[+-]\d{2}:\d{2}$//; # Strip TimeZone
                    if ($date && (!$oldest || $date lt $oldest)) {
                        $oldest = $date;
                    }
                }
                return $oldest;
            },
    PrintConv => '$self->ConvertDateTime($val)',
        },
    },
);

1;


Command to update files with the oldest date :

exiftool -config /path/to/oldest_datetime_config "-SubSecDateTimeOriginal<OldestDateTime" "-XMP:DateCreated<OldestDateTime" "/path/to/photo/IMG.jpg"

pedroreis

Quote from: StarGeek on November 09, 2021, 10:52:54 AM
I'm not sure what you're asking.  Do you want the current date or the oldest date?

You can set a time stamp to the current date/time with now
exiftool -DateTimeOriginal=now file.jpg

But if your config is working correctly, then go with it.

Hi!

I'm trying to find the oldest date and also detect problems like date being in the future, as already happened in some files.
So I was trying to get today's date and compare .
It seems is possible to have

use POSIX qw(strftime);
$now = strftime "%Y:%m:%d", localtime;
print "Todays' date is $now\n";


outside the

%Image::ExifTool::UserDefined = (

block.

But:
1) breaks execution when inside it.
(get this warning, as well : exiftool.exe : Warning: No writable tags set from ./IMG_20220610_134025.jpg)

2) I also get an error when trying to use the $now variable created outside!

Is this impossible to do?

kav205

#24
Hi.
I have many files without EXIF information, and with EXIF.
All the files are placed in subfolders. All the subfolders' names begin with a date, for example - "1902_01_15 Birthday uncle".
The script sets the "DateTimeOriginal" TAG, if the exif is absent or blank.
The value of the DateTimeOriginal field is taken from the subfolder's name, where the file is placed.
Files with set value of DateTimeOriginal will not changed!!!

Below text bat(cmd) file for windows.
**********************
SETLOCAL ENABLEDELAYEDEXPANSION
ECHO OFF
REM Path for exiftool.exe
SET AppPath=d:\w\exiftool\exiftool.exe

for /f "tokens=*" %%G in ('DIR /B /AD') do CALL :OBR "%%G"
GOTO END

:OBR
SET fld=%1
SET datat=%fld:~1,4%:%fld:~6,2%:%fld:~9,2%
"%AppPath%" -m -quiet -if "$DateTimeOriginal eq ''" "-DateTimeOriginal=%datat% 00:00:00" %1
GOTO :EOF

:END
pause


This is my first batch file.

StarGeek Edit: Edited to correct formatting.  Please use the button for commands and button for sample exiftool output and code.

StarGeek

This batch file calls exiftool once for each file.  This is Common Mistake #3.  Exiftool's greatest performance hit is the startup time and calling exiftool once for each file will significantly increase the processing time.

A better option would be to pipe the output of dir directly into exiftool, so the entire loop could be replaced with this (I think, I haven't tested it)
DIR /B /AD | "%AppPath%" -m -quiet -if "$DateTimeOriginal eq ''" "-DateTimeOriginal=%datat% 00:00:00" -@ -

The -@ (Argfile) option with - as the filename will read the file list directly from the pipe.
"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

ptewari

Hi, I added the commands based on the config provided by djcroustibat here: https://github.com/pratyushtewari/exif-scripts/blob/master/README.md

RVis

Hi there,

I had a ransomware issue on my NAS.
I was able to recover my files from multiple sources of external storage (absolutely not possible to pay).
With over 100k files to reorganize and new to exiftool, I make myself a basic bat script to reorganize this automatically with oldest date.

My first way of working was going to last several days (4 or 5), it launched exiftool with each file.
So I changed the way of processing the files and it's now really faster, I can't imagine having that much difference in processing time. On my last test it does 2000 files in 9 minutes 30 so something like 8/9h for my 100k! (definitely improvable because I'm not a real and good programmer)

I put you my last version for those who wish to have a base or decide to use it as it is.

What the script does:
1 - Checks if all paths are correct or if some problems occur
2 - Save all EXIF data in text files
3 - Analyze all txt files to determine the oldest date
4 - Move and rename my files to year/month/[date] (time) counter.extension
5 - Delete all empty folders at the end.

It is possible to define file extensions to process, EXIFs TAGs and some dates to ignore.
It also writes an xml file, I find it easier to do some manual checks later by opening this file in excel.

StarGeek

Quote from: RVis on September 09, 2022, 07:14:38 PMit launched exiftool with each file.
So I changed the way of processing the files and it's now really faster, I can't imagine having that much difference in processing time.

This is Common Mistake #3.  The startup time for exiftool is significant, as it has to set up the internal data for all 25,000+ tags it can read among other things.  Exiftool is still a Perl program and Perl is an interpreted language. Even the Windows executable is the Perl code and a basic Perl interpreter.
"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

wywh

#29
Quote from: Hayo Baan on January 13, 2017, 03:39:16 AMbelow config file content will do what you want

Thanks, that works fine. I added Keys:CreationDate for movie support to the oldest_datetime_config:

%Image::ExifTool::UserDefined = (
    'Image::ExifTool::Composite' => {
        # Select oldest date from a number of date tags
        OldestDateTime => {
            Desire => {
                0 => 'FileModifyDate',
                1 => 'MDItemFSContentChangeDate',
                2 => 'FileCreateDate',
                3 => 'MDItemFSCreationDate',
                4 => 'ModifyDate',
                5 => 'CreateDate',
                6 => 'DateTimeCreated',
                7 => 'DateTimeOriginal',
                8 => 'CreationDate',
            },
            ValueConv => q{
                my $oldest = undef;
                for my $date (@val) {
                    $date =~ s/[+-]\d{2}:\d{2}$//; # Strip TimeZone
                    if ($date && (!$oldest || $date lt $oldest)) {
                        $oldest = $date;
                    }
                }
                return $oldest;
            },
        },
    },
);

1;

So for example, check the oldest image or movie datetime (with '-api RequestAll=2' also FileCreateDate is factored in):

exiftool -config oldest_datetime_config -a -G1 -s -fileOrder5 FileName -api QuickTimeUTC=1 -api RequestAll=2 -FileName -OldestDateTime .
To set all image dates to that oldest date, use something like this (I prefer to set all relevant dates the same so spotting a wrong date is easier):

exiftool -config oldest_datetime_config -m -overwrite_original_in_place -wm w -api RequestAll=2 '-AllDates<OldestDateTime' '-DateCreated<OldestDateTime' '-TimeCreated<OldestDateTime' '-DigitalCreationDate<OldestDateTime' '-DigitalCreationTime<OldestDateTime' '-FileCreateDate<OldestDateTime' '-FileModifyDate<OldestDateTime' image.jpg
To set all movie dates to that oldest date, use something like this:

exiftool -config oldest_datetime_config -m -overwrite_original_in_place -wm w -api QuickTimeUTC=1 -api RequestAll=2 '-AllDates<OldestDateTime' '-Track*Date<OldestDateTime' '-Media*Date<OldestDateTime' '-Keys:CreationDate<OldestDateTime' '-FileCreateDate<OldestDateTime' '-FileModifyDate<OldestDateTime' movie.mp4
On macOS 13.4 that works down to year 1904 with QuickTime:CreateDate, and to 1677:09:21 with other tags. But I'd be careful with dates before 1970 anyway because some apps might be picky about earlier dates and non-Mac filesystems might have corrupted the file dates.

- Matti