Main Menu

Recent posts

#1
Quote from: maxardis on Today at 06:52:02 AMI am trying to do this:

exiftool -p '${exif:DateTimeOriginal;ShiftTime(${exif:OffsetTimeOriginal}, -1)} ${directory}/${filename}' ./dir/*

And what I get is a warning:
Warning: Bareword "OffsetTimeOriginal" not allowed while "strict subs" in use for 'exif:DateTimeOriginal'.  I don't understand that message and I don't know what I am doing wrong, nor how to fix it.

Nice attempt, but it isn't that simple to access a different tag within the processing of another tag. The error message is directly from the underlying Perl processor. Accessing a second tag from within a tag can be done, but I think this would be a better way.

First, instead of using DateTimeOriginal, use SubSecDateTimeOriginal.  This is a Composite tag that combines DateTimeOriginal, OffsetTimeOriginal, and SubSecTimeOriginal.  Then the DateFmt helper function is used to convert that to a Unix time stamp, the internal exiftool function of ConvertUnixTime is used to convert that to a normal date in the standard EXIF format (colons instead of hyphens), and DateFmt is used again to convert that into the format you're looking for.

Example
C:\>exiftool -G1 -a -s -SubSecDateTimeOriginal y:\!temp\Test4.jpg
[Composite]     SubSecDateTimeOriginal          : 2024:05:20 12:00:00-07:00

C:\>exiftool -p "${SubSecDateTimeOriginal;DateFmt('%s');$_=ConvertUnixTime($_);DateFmt('%Y-%m-%dT%H:%M:%S')}" y:\!temp\Test4.jpg
2024-05-20T19:00:00

You don't mention your OS, but you appear to be on Mac/Linux.  The above command would be for Windows CMD, so you'll have to swap double/single quotes.
#2
Newbies / Re: How to extract the content...
Last post by FixEUser - Today at 08:56:52 AM
I think, I have found a workaround with a Windows batch file.
This may be a little bit more convenient for Windows users.

Write (copy & paste) this code in a batch file and name it like
ShowContentOfThisUndefinedText.cmd

ECHO OFF
@CLS
SETLOCAL enabledelayedexpansion
FOR /F "tokens=2 delims=)" %%M IN ('   
    exiftool.exe -a -UserDefinedText -ext mp3 -recurse . ^| findstr /c:%1 /i
    ') DO (   
          SET LeftTrimmedValue=%%M         
          ECHO !LeftTrimmedValue:~1!         
          )

This batch file assumes, that exiftool.exe is in the same directory as the batch.
Otherwise, you have to write the full path to your exiftool.exe like
C:\Path\To\My\exiftool.exe

Then copy the batch file to the root directory in which the mp3 files to be checked are stored.

Open a CMD window in this root directory.

Start the batch file and add the string you want to search for in the UndefinedText ID3 tag like this:
ShowContentOfThisUndefinedText "musicbrainz album artist id"and you get the wanted
d87e52c5-bb8d-4da8-b941-9f4928627dc8

Explanations for the batch code:
1) exiftool shows all the ID3 TXXX tags (aka "UserDefinedText") for all mp3 files recursively
2) the Windows command FINDSTR searches for all lines that contain the given string like "musicbrainz album artist id" case-IN-sensitive
3) to get only the tag content (neither "UserDefinedText" nor the tag name in brackets), only the second token after the closing bracket will be outputted
3) to left trim the found content, the first character will be stripped away

Remark:
This batch is only intended for MP3 files and the ID3 TXXX "UserDefinedText" tag.
#3
Hello,

What I would like is to generate dates(*) in UTC (in ISO format) from exif tags for all files in directory without modifying files.

Similarly to a tool like sha1sum I would like to write something like: exiftool (magic options here...) ./directory/* and get output to stdout like so:

2024-01-01T10:10:10  ./directory/file1.jpg
2024-01-01T10:11:10  ./directory/file2.jpg
2024-01-02T10:10:10  ./directory/file3.jpg
...

Output similar to sha1sum but instead of hashes I get dates.

(*) When I say dates what I mean exactly is combination of tags exif:DateTimeOriginal + exif:OffsetTimeOriginal.


What I was able to figure out is:

$ exiftool -d '%Y-%m-%dT%H:%M:%S' -p '${exif:DateTimeOriginal}${exif:OffsetTimeOriginal} ${directory}/${filename}' ./dir/*

This gives me almost what I want.  It gives me the information to stdout in format similar to sha1sum, it gives me dates in ISO format, but it doesn't give me the dates in UTC.

By googling around I can see that there is something like ShiftTime() function that maybe I could use, but unfortunately I cannot make it work.  So I am here for your help.


I am trying to do this:

exiftool -p '${exif:DateTimeOriginal;ShiftTime(${exif:OffsetTimeOriginal}, -1)} ${directory}/${filename}' ./dir/*

And what I get is a warning: Warning: Bareword "OffsetTimeOriginal" not allowed while "strict subs" in use for 'exif:DateTimeOriginal'.  I don't understand that message and I don't know what I am doing wrong, nor how to fix it.

Hope you can help me here.  Thank you in advance.
#4
Newbies / Re: How to extract the content...
Last post by FixEUser - Today at 04:48:34 AM
Thank you for your attempt.

There are at least 3 problems with your script:

1) It doesn't return any other value then without -config join_tags_ID3-config
2) It returns an error "join_tags_ID3.config did not return a true value at Image/ExifTool.pm line 9675."
3) For other readers: The config file needs to be named exactly the same as you use it in the command line:
exiftool -config join_tags_ID3.config -G1 -a -s -UserDefinedText Y:\temp\x\y\test.mp3

@StarGeek: I'm not sure if you understand my initial question:

I asked for a solution to get 1 (one) specific tag content, for example "MusicBrainz Album Artist Id".
The idea would be a (not yet working) syntax like
exiftool -config specificID3.config -G1 -a -s -UserDefinedText("MusicBrainz Album Artist Id") music.mp3and then get only this value:
d87e52c5-bb8d-4da8-b941-9f4928627dc8

How could I achieve that?

PS
Are you sure that
my $table = Image::ExifTool::GetTagTable('Image::ExifTool::Composite');
is the correct way to get the UserDefinedText content?
#5
Newbies / Re: Help requested - Syntax Co...
Last post by StarGeek - May 19, 2024, 08:40:48 PM
One thing that comes to mind is the sidecar files. They might (probably?) not have the same file system time stamps as the main files.

Also, you say "original create date on the file (not the last modified" but you are using CreateDate, not the file system tag, FileCreateDate. CreateDate is a tag embedded in the file and should just about always be exactly the same as DateTimeOriginal, though DateTimeOriginal is less likely to be in videos.

But then you run into the problem that the CreateDate in video files is set to UTC, not local time.  I believe that iPhones will set CreationDate to the local time, so you might put an entry for that to the right of CreateDate.

And you can always test things out by using Testname instead of Filename.  That will output what the file path/name would be without actually moving the file.
#6
Newbies / Re: How to extract the content...
Last post by StarGeek - May 19, 2024, 04:08:22 PM
Ok, I got an idea and was able to edit the join_tags.config to make something that may work.

#------------------------------------------------------------------------------
# File:         join_tags_ID3.config
#
# Description:  ExifTool config file to generate new tags from ID3:UserDefinedText,
# based upon the original join_tags.config
#
# Revisions:    2020-11-16 - P. Harvey created
# 2024-05-19 - Bryan (StarGeek) Williams edited
#
#------------------------------------------------------------------------------

my $nameTag = 'UserDefinedText';

sub JoinTags($$)
{
    my ($val, $et) = @_;
    my $table = Image::ExifTool::GetTagTable('Image::ExifTool::Composite');
    my $i;
    for ($i=0; ;++$i) {
        my $suffix = $i ? " ($i)" : '';
my $temp = $et->GetValue("$nameTag$suffix") or last;
$temp=~m/^\(([^)]+)\)\s*(.*)/;
my $name = $1 or last;
        my $value = $2;
        last unless defined $value;
        my $tagInfo = Image::ExifTool::AddTagToTable($table, $name, {
            Name => Image::ExifTool::MakeTagName($name),
        });
        $et->FoundTag($tagInfo, $value);
    }
    return undef;
}

%Image::ExifTool::UserDefined = (
    'Image::ExifTool::Composite' => {
        JoinTagsID3 => {
            Desire => {
                0 => $nameTag,
                1 => $valueTag,
            },
            RawConv => \&JoinTags,
        },
    },
);

1; #end

This will look at the UserDefinedText tags, parse out the data between the parentheses (only if it is at the start of the tag data), create a tag name based upon that, and give that tag a value equal to the rest of the string, trimming leading spaces.

A couple of tests.
C:\>exiftool -config join_tags_ID3.config -G1 -a -s -UserDefinedText -Composite:all Y:\!temp\x\y\test1.mp3
[ID3v2_3]       UserDefinedText                 : (Rip date) 2008-06-22
[ID3v2_3]       UserDefinedText                 : (Source) CD (LP)
[ID3v2_3]       UserDefinedText                 : (Ripping tool) EAC
[ID3v2_3]       UserDefinedText                 : (Release type) Normal Release
[Composite]     DateTimeOriginal                : 2008:24:06
[Composite]     AudioBitrate                    : 206 kbps
[Composite]     Duration                        : 0:03:22 (approx)
[Composite]     Releasetype                     : Normal Release
[Composite]     Ripdate                         : 2008-06-22
[Composite]     Source                          : CD (LP)
[Composite]     Rippingtool                     : EAC

Here's one I thought would break it.  It has a tag with "([rating]) 3" and another with "(Rating) 0".  I thought the brackets might break this.
C:\>exiftool -config join_tags_ID3.config -G1 -a -s -UserDefinedText -composite:all Y:\!temp\x\y\test2.mp3
[ID3v2_3]       UserDefinedText                 : ([rating]) 3
[ID3v2_3]       UserDefinedText                 : (Release type) Normal release
[ID3v2_3]       UserDefinedText                 : (Rip date) 2007-09-14
[ID3v2_3]       UserDefinedText                 : (Ripping tool) EAC
[ID3v2_3]       UserDefinedText                 : (Source) CD
[ID3v2_3]       UserDefinedText                 : (Rating) 0
[Composite]     DateTimeOriginal                : 2007:11:09
[Composite]     AudioBitrate                    : 186 kbps
[Composite]     Duration                        : 0:03:45 (approx)
[Composite]     Rating                          : 0
[Composite]     Rating                          : 3
[Composite]     Releasetype                     : Normal release
[Composite]     Ripdate                         : 2007-09-14
[Composite]     Rippingtool                     : EAC
[Composite]     Source                          : CD

I do not know what will happen if there's a UserDefinedText tag that does not start with parentheses.  It might break in that case. If it does, send me a sample and I'll see if I can fix it.
#7
Newbies / Re: How to extract the content...
Last post by StarGeek - May 19, 2024, 03:10:25 PM
Quote from: FixEUser on May 19, 2024, 07:58:15 AMHow can I extract the content of a specific ID3 "User Defined Text" tag?

To get a specific one might take a user defined tag.

QuoteWhat exiftool-syntax would it be if the only way to get the content is using "ID3:Copy4"?
This won't work as you have specified an actual tag name. You could try ID3:Copy4:UserDefinedText but that assumes the item you are looking for is in the exact same location for every file, which seems unlikely.

With a user defined tag, you could look through all copies of that tag to find the correct one and return that.  But the problem is how to pass all copies of that tag name. I'm pretty sure I asked this question once, but can't remember the context, so it's hard to search for it.

I'll keep trying to figure it out, but it may require input from Phil.
#8
The page DNG Tags has a stale link to the DNG spec:
http://www.adobe.com/products/dng/

The current location for the spec is here:
https://helpx.adobe.com/camera-raw/digital-negative.html
#9
Newbies / How to extract the content of ...
Last post by FixEUser - May 19, 2024, 07:58:15 AM
How can I extract the content of a specific ID3 "User Defined Text" tag?

Imagine you find this content in the tags of your mp3 file:

Album Artist Sort Order         : ABBA
User Defined Text               : (ARTISTS) ABBA
User Defined Text               : (BARCODE) 602498664636
User Defined Text               : (CATALOGNUMBER) 0602498664636
User Defined Text               : (MusicBrainz Album Artist Id) d87e52c5-bb8d-4da8-b941-9f4928627dc8
User Defined Text               : (MusicBrainz Album Id) 6b1d9e00-246f-4701-8f7f-57f7d2d998e6
User Defined Text               : (MusicBrainz Album Release Country) XE
User Defined Text               : (MusicBrainz Album Status) Official
User Defined Text               : (MusicBrainz Album Type) Album
User Defined Text               : (MusicBrainz Artist Id) d87e52c5-bb8d-4da8-b941-9f4928627dc8
User Defined Text               : (MusicBrainz Release Group Id) 1f78ea53-5e9c-46b6-8cd4-9d8a9c547a85
User Defined Text               : (MusicBrainz Release Track Id) 594c05ce-bbb5-45cd-b971-4e268d3b137b
User Defined Text               : (originalyear) 1974
User Defined Text               : (SCRIPT) Latn
Picture MIME Type               : image/jpeg

What is the most easy exiftool-syntax to get the "MusicBrainz Album Artist Id" only?

I learned, that we have the
-a -g0:4options to get something like this:
---- ID3:Copy4 ----
User Defined Text               : (MusicBrainz Album Artist Id) d87e52c5-bb8d-4da8-b941-9f4928627dc8
What exiftool-syntax would it be if the only way to get the content is using "ID3:Copy4"?
#10
Newbies / Help requested - Syntax Confir...
Last post by Povitch - May 19, 2024, 07:33:17 AM
Hi,

I am trying to do the following with the enclosed syntax. I would appreciate if you could confirm I have it correct. Truthfully, I have so many in such a mess, I am scared to try too much without this confirmation in case I make things worse! Many thanks.

Take a directory and move all the files
- photos (jpg, heic, Raw) including AAE side car files for apples Portrait mode and any edits AND mov files for live photos
-Movie files from iphones etc.
File move to a new directory structure, YYYY MM DD based on the rule where it looks for the original create date on the file (not the last modified - so it doesn't move based on when the file was moved in Finder last)

I want to keep all the files and their sidecars together essentially and take care of any where the file modification date is after the creation date.

Also, if there are duplicate files, I want to move them as well, so I can run a dedupe process post move, and the duplicate files need to be appended with a -1 -2 etc. I will be running this process multiple times and there may be duplicates from run 2 to put alongside a photo from run 1 etc.

I hope all that makes sense?

Here is my syntax:

exiftool -r -d "/some/other/directory/specification/%Y/%m/%d/%%f%%-c.%%e" "-api largefilesupport" -filename<filemodifydate" "-filename<createdate" "-filename<datetimeoriginal"