Importing XML:Cast into an MP4 file

Started by bcurran3, November 19, 2023, 06:50:06 PM

Previous topic - Next topic

bcurran3

Hi Phil and everyone,

I've been banging my head against the monitor for long time now. I'm finally and humbly giving up and... asking for help. Yes, I've S(kimmed)TFM.

GOAL: Add Actors/Cast info to MP4 files using ExifTool systematically.

PROBLEM:
Intuitively I think that
exiftool -cast="Someone"would work. As I and everyone else who tried to do this before finds out,
Warning: Sorry, cast is not writable
Nothing to do.
is the result.  >:(

Whenever I search for a solution, I always come across this ExifTool Forum post from 2010 stating
QuoteExifTool will import from the RDF/XML files that it writes, but won't import from arbitrary XML files.
8)

So I got happy thinking I've got a workable solution... I'll just add some fake Actors/Cast info to a file using a different program (MetaX for Windows), use ExifTool to extract the XML data as a reusable template, modify the XML data, then import it back using the -tagsfromfile option.

I can't get that to work.  >:(

Here's what I did:

Extract the current Actors/Cast data:
exiftool -X -t -XML:Cast test.mp4 > test.xml
Which yields:
<?xml version='1.0' encoding='UTF-8'?>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>

<rdf:Description rdf:about='test.mp4'
  xmlns:et='http://ns.exiftool.org/1.0/' et:toolkit='Image::ExifTool 12.40'
  xmlns:XML='http://ns.exiftool.org/PLIST/XML/1.0/'>
 <XML:Cast et:id='cast//name' et:table='PLIST::Main'>
  <rdf:Bag>
   <rdf:li>Person One</rdf:li>
   <rdf:li>Person Two</rdf:li>
  </rdf:Bag>
 </XML:Cast>
</rdf:Description>
</rdf:RDF>

Edit that file to this as a test:
<?xml version='1.0' encoding='UTF-8'?>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>

<rdf:Description rdf:about='test.mp4'
  xmlns:et='http://ns.exiftool.org/1.0/' et:toolkit='Image::ExifTool 12.40'
  xmlns:XML='http://ns.exiftool.org/PLIST/XML/1.0/'>
 <XML:Cast et:id='cast//name' et:table='PLIST::Main'>
  <rdf:Bag>
   <rdf:li>Person Three</rdf:li>
   <rdf:li>Person Four</rdf:li>
  </rdf:Bag>
 </XML:Cast>
</rdf:Description>
</rdf:RDF>

Then try to import that modified data:
exiftool -tagsfromfile test.xml test.mp4
The result I get is:
Warning: No writable tags set from test.xml
    0 image files updated
    1 image files unchanged

I've tried with ExifTool v12.69 for Windows and ExifTool v12.40 for Linux. No luck with either.

I'm really, really, really, really, hoping it's a simple TLDR oversight of mine and you're going to respond something like "Hi Bill. You need to additionally use the -blah switch and it will work as expected."  ;) Then I can go put ice on this bump on my head.

bcurran3

p.s. I tried exporting and importing a CSV file as well using the same methodology and got the same result.

StarGeek

From the looks of your command and that you are reading XML:Cast, it looks like this is some XML embedded in the file.  Exiftool cannot write/edit XML data in a file.

Can you share the file?  Maybe there's a tag that holds the XML data and you can the -TAG<=DATFILE option to embed the XML as a block.  Though it is a long shot.
"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

bcurran3

Sure thing. I went out to examplefile.com and grabbed this super small MP4 file and added fake cast info to it with MetaX (Dan Hinsley is the developer. I'm pretty sure I read a discussion between you two on here long ago.) but I can't attach here (and completely understand why). I'll find a place to dump and share later.

Maybe this will help:
<?xml version='1.0' encoding='UTF-8'?>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>

<rdf:Description rdf:about='./file_example_MP4_480_1_5MG.mp4'
  xmlns:et='http://ns.exiftool.org/1.0/' et:toolkit='Image::ExifTool 12.69'
  xmlns:ExifTool='http://ns.exiftool.org/ExifTool/1.0/'
  xmlns:System='http://ns.exiftool.org/File/System/1.0/'
  xmlns:File='http://ns.exiftool.org/File/1.0/'
  xmlns:QuickTime='http://ns.exiftool.org/QuickTime/QuickTime/1.0/'
  xmlns:Track1='http://ns.exiftool.org/QuickTime/Track1/1.0/'
  xmlns:Track2='http://ns.exiftool.org/QuickTime/Track2/1.0/'
  xmlns:Microsoft='http://ns.exiftool.org/QuickTime/Microsoft/1.0/'
  xmlns:XML='http://ns.exiftool.org/PLIST/XML/1.0/'
  xmlns:ItemList='http://ns.exiftool.org/QuickTime/ItemList/1.0/'
  xmlns:Track3='http://ns.exiftool.org/QuickTime/Track3/1.0/'
  xmlns:Composite='http://ns.exiftool.org/Composite/1.0/'>
 <ExifTool:ExifToolVersion et:id='ExifToolVersion' et:table='Extra'>12.69</ExifTool:ExifToolVersion>
 <System:FileName et:id='FileName' et:table='Extra'>file_example_MP4_480_1_5MG.mp4</System:FileName>
 <System:Directory et:id='Directory' et:table='Extra'>.</System:Directory>
 <System:FileSize et:id='FileSize' et:table='Extra'>1583 kB</System:FileSize>
 <System:ZoneIdentifier et:id='ZoneIdentifier' et:table='Extra'>Exists</System:ZoneIdentifier>
 <System:FileModifyDate et:id='FileModifyDate' et:table='Extra'>2023:11:20 18:26:36-08:00</System:FileModifyDate>
 <System:FileAccessDate et:id='FileAccessDate' et:table='Extra'>2023:11:20 18:30:31-08:00</System:FileAccessDate>
 <System:FileCreateDate et:id='FileCreateDate' et:table='Extra'>2023:11:20 18:26:36-08:00</System:FileCreateDate>
 <System:FilePermissions et:id='FilePermissions' et:table='Extra'>-rw-rw-rw-</System:FilePermissions>
 <File:FileType et:id='FileType' et:table='Extra'>MP4</File:FileType>
 <File:FileTypeExtension et:id='FileTypeExtension' et:table='Extra'>mp4</File:FileTypeExtension>
 <File:MIMEType et:id='MIMEType' et:table='Extra'>video/mp4</File:MIMEType>
 <QuickTime:MajorBrand et:id='0' et:table='QuickTime::FileType'>MP4 v2 [ISO 14496-14]</QuickTime:MajorBrand>
 <QuickTime:MinorVersion et:id='1' et:table='QuickTime::FileType'>0.0.0</QuickTime:MinorVersion>
 <QuickTime:CompatibleBrands et:id='2' et:table='QuickTime::FileType'>
  <rdf:Bag>
  <rdf:li>mp42</rdf:li>
  <rdf:li>mp41</rdf:li>
  <rdf:li>isom</rdf:li>
  <rdf:li>avc1</rdf:li>
  </rdf:Bag>
 </QuickTime:CompatibleBrands>
 <QuickTime:MediaDataSize et:id='mdat-size' et:table='QuickTime::Main'>1558152</QuickTime:MediaDataSize>
 <QuickTime:MediaDataOffset et:id='mdat-offset' et:table='QuickTime::Main'>11872</QuickTime:MediaDataOffset>
 <QuickTime:MediaDataSize et:id='mdat-size' et:table='QuickTime::Main'>23</QuickTime:MediaDataSize>
 <QuickTime:MediaDataOffset et:id='mdat-offset' et:table='QuickTime::Main'>1570032</QuickTime:MediaDataOffset>
 <QuickTime:MovieHeaderVersion et:id='0' et:table='QuickTime::MovieHeader'>0</QuickTime:MovieHeaderVersion>
 <QuickTime:CreateDate et:id='1' et:table='QuickTime::MovieHeader'>2015:08:07 09:13:02</QuickTime:CreateDate>
 <QuickTime:ModifyDate et:id='2' et:table='QuickTime::MovieHeader'>2023:11:21 02:27:40</QuickTime:ModifyDate>
 <QuickTime:TimeScale et:id='3' et:table='QuickTime::MovieHeader'>600</QuickTime:TimeScale>
 <QuickTime:Duration et:id='4' et:table='QuickTime::MovieHeader'>0:00:31</QuickTime:Duration>
 <QuickTime:PreferredRate et:id='5' et:table='QuickTime::MovieHeader'>1</QuickTime:PreferredRate>
 <QuickTime:PreferredVolume et:id='6' et:table='QuickTime::MovieHeader'>100.00%</QuickTime:PreferredVolume>
 <QuickTime:MatrixStructure et:id='9' et:table='QuickTime::MovieHeader'>1 0 0 0 1 0 0 0 1</QuickTime:MatrixStructure>
 <QuickTime:PreviewTime et:id='18' et:table='QuickTime::MovieHeader'>0 s</QuickTime:PreviewTime>
 <QuickTime:PreviewDuration et:id='19' et:table='QuickTime::MovieHeader'>0 s</QuickTime:PreviewDuration>
 <QuickTime:PosterTime et:id='20' et:table='QuickTime::MovieHeader'>0 s</QuickTime:PosterTime>
 <QuickTime:SelectionTime et:id='21' et:table='QuickTime::MovieHeader'>0 s</QuickTime:SelectionTime>
 <QuickTime:SelectionDuration et:id='22' et:table='QuickTime::MovieHeader'>0 s</QuickTime:SelectionDuration>
 <QuickTime:CurrentTime et:id='23' et:table='QuickTime::MovieHeader'>0 s</QuickTime:CurrentTime>
 <QuickTime:NextTrackID et:id='24' et:table='QuickTime::MovieHeader'>4</QuickTime:NextTrackID>
 <QuickTime:HandlerType et:id='8' et:table='QuickTime::Handler'>Metadata</QuickTime:HandlerType>
 <Track1:TrackHeaderVersion et:id='0' et:table='QuickTime::TrackHeader'>0</Track1:TrackHeaderVersion>
 <Track1:TrackCreateDate et:id='1' et:table='QuickTime::TrackHeader'>2015:08:07 09:13:02</Track1:TrackCreateDate>
 <Track1:TrackModifyDate et:id='2' et:table='QuickTime::TrackHeader'>2015:08:07 09:13:02</Track1:TrackModifyDate>
 <Track1:TrackID et:id='3' et:table='QuickTime::TrackHeader'>1</Track1:TrackID>
 <Track1:TrackDuration et:id='5' et:table='QuickTime::TrackHeader'>0:00:30</Track1:TrackDuration>
 <Track1:TrackLayer et:id='8' et:table='QuickTime::TrackHeader'>0</Track1:TrackLayer>
 <Track1:TrackVolume et:id='9' et:table='QuickTime::TrackHeader'>0.00%</Track1:TrackVolume>
 <Track1:MatrixStructure et:id='10' et:table='QuickTime::TrackHeader'>1 0 0 0 1 0 0 0 1</Track1:MatrixStructure>
 <Track1:ImageWidth et:id='19' et:table='QuickTime::TrackHeader'>480</Track1:ImageWidth>
 <Track1:ImageHeight et:id='20' et:table='QuickTime::TrackHeader'>270</Track1:ImageHeight>
 <Track1:MediaHeaderVersion et:id='0' et:table='QuickTime::MediaHeader'>0</Track1:MediaHeaderVersion>
 <Track1:MediaCreateDate et:id='1' et:table='QuickTime::MediaHeader'>2015:08:07 09:13:02</Track1:MediaCreateDate>
 <Track1:MediaModifyDate et:id='2' et:table='QuickTime::MediaHeader'>2015:08:07 09:13:02</Track1:MediaModifyDate>
 <Track1:MediaTimeScale et:id='3' et:table='QuickTime::MediaHeader'>30</Track1:MediaTimeScale>
 <Track1:MediaDuration et:id='4' et:table='QuickTime::MediaHeader'>0:00:30</Track1:MediaDuration>
 <Track1:MediaLanguageCode et:id='5' et:table='QuickTime::MediaHeader'>eng</Track1:MediaLanguageCode>
 <Track1:HandlerType et:id='8' et:table='QuickTime::Handler'>Video Track</Track1:HandlerType>
 <Track1:HandlerDescription et:id='24' et:table='QuickTime::Handler'>L-SMASH Video Handler</Track1:HandlerDescription>
 <Track1:GraphicsMode et:id='2' et:table='QuickTime::VideoHeader'>srcCopy</Track1:GraphicsMode>
 <Track1:OpColor et:id='3' et:table='QuickTime::VideoHeader'>0 0 0</Track1:OpColor>
 <Track1:CompressorID et:id='2' et:table='QuickTime::ImageDesc'>avc1</Track1:CompressorID>
 <Track1:SourceImageWidth et:id='16' et:table='QuickTime::ImageDesc'>480</Track1:SourceImageWidth>
 <Track1:SourceImageHeight et:id='17' et:table='QuickTime::ImageDesc'>270</Track1:SourceImageHeight>
 <Track1:XResolution et:id='18' et:table='QuickTime::ImageDesc'>72</Track1:XResolution>
 <Track1:YResolution et:id='20' et:table='QuickTime::ImageDesc'>72</Track1:YResolution>
 <Track1:CompressorName et:id='25' et:table='QuickTime::ImageDesc'>AVC Coding</Track1:CompressorName>
 <Track1:BitDepth et:id='41' et:table='QuickTime::ImageDesc'>0</Track1:BitDepth>
 <Track1:PixelAspectRatio et:id='pasp' et:table='QuickTime::ImageDesc'>1:1</Track1:PixelAspectRatio>
 <Track1:VideoFrameRate et:id='stts' et:table='QuickTime::SampleTable' et:index='0'>30</Track1:VideoFrameRate>
 <Track1:ChapterListTrackID et:id='chap' et:table='QuickTime::TrackRef'>3</Track1:ChapterListTrackID>
 <Track2:TrackHeaderVersion et:id='0' et:table='QuickTime::TrackHeader'>0</Track2:TrackHeaderVersion>
 <Track2:TrackCreateDate et:id='1' et:table='QuickTime::TrackHeader'>2015:08:07 09:13:02</Track2:TrackCreateDate>
 <Track2:TrackModifyDate et:id='2' et:table='QuickTime::TrackHeader'>2015:08:07 09:13:02</Track2:TrackModifyDate>
 <Track2:TrackID et:id='3' et:table='QuickTime::TrackHeader'>2</Track2:TrackID>
 <Track2:TrackDuration et:id='5' et:table='QuickTime::TrackHeader'>0:00:31</Track2:TrackDuration>
 <Track2:TrackLayer et:id='8' et:table='QuickTime::TrackHeader'>0</Track2:TrackLayer>
 <Track2:TrackVolume et:id='9' et:table='QuickTime::TrackHeader'>100.00%</Track2:TrackVolume>
 <Track2:MatrixStructure et:id='10' et:table='QuickTime::TrackHeader'>1 0 0 0 1 0 0 0 1</Track2:MatrixStructure>
 <Track2:MediaHeaderVersion et:id='0' et:table='QuickTime::MediaHeader'>0</Track2:MediaHeaderVersion>
 <Track2:MediaCreateDate et:id='1' et:table='QuickTime::MediaHeader'>2015:08:07 09:13:02</Track2:MediaCreateDate>
 <Track2:MediaModifyDate et:id='2' et:table='QuickTime::MediaHeader'>2015:08:07 09:13:02</Track2:MediaModifyDate>
 <Track2:MediaTimeScale et:id='3' et:table='QuickTime::MediaHeader'>48000</Track2:MediaTimeScale>
 <Track2:MediaDuration et:id='4' et:table='QuickTime::MediaHeader'>0:00:31</Track2:MediaDuration>
 <Track2:MediaLanguageCode et:id='5' et:table='QuickTime::MediaHeader'>und</Track2:MediaLanguageCode>
 <Track2:HandlerType et:id='8' et:table='QuickTime::Handler'>Audio Track</Track2:HandlerType>
 <Track2:HandlerDescription et:id='24' et:table='QuickTime::Handler'>L-SMASH Audio Handler</Track2:HandlerDescription>
 <Track2:Balance et:id='2' et:table='QuickTime::AudioHeader'>0</Track2:Balance>
 <Track2:AudioFormat et:id='4' et:table='QuickTime::AudioSampleDesc'>mp4a</Track2:AudioFormat>
 <Track2:AudioChannels et:id='24' et:table='QuickTime::AudioSampleDesc'>2</Track2:AudioChannels>
 <Track2:AudioBitsPerSample et:id='26' et:table='QuickTime::AudioSampleDesc'>16</Track2:AudioBitsPerSample>
 <Track2:AudioSampleRate et:id='32' et:table='QuickTime::AudioSampleDesc'>48000</Track2:AudioSampleRate>
 <Microsoft:SharedUserRating et:id='WM/SharedUserRating' et:table='Microsoft::Xtra'>0</Microsoft:SharedUserRating>
 <XML:Cast et:id='cast//name' et:table='PLIST::Main'>
  <rdf:Bag>
  <rdf:li>actor one</rdf:li>
  <rdf:li>actor two</rdf:li>
  </rdf:Bag>
 </XML:Cast>
 <ItemList:Title et:id='\xa9nam' et:table='QuickTime::ItemList'>file_example_MP4_480_1_5MG</ItemList:Title>
 <ItemList:HDVideo et:id='hdvd' et:table='QuickTime::ItemList'>No</ItemList:HDVideo>
 <ItemList:MediaType et:id='stik' et:table='QuickTime::ItemList'>Unknown (3)</ItemList:MediaType>
 <Track3:TrackHeaderVersion et:id='0' et:table='QuickTime::TrackHeader'>0</Track3:TrackHeaderVersion>
 <Track3:TrackCreateDate et:id='1' et:table='QuickTime::TrackHeader'>2023:11:21 02:27:40</Track3:TrackCreateDate>
 <Track3:TrackModifyDate et:id='2' et:table='QuickTime::TrackHeader'>2023:11:21 02:27:40</Track3:TrackModifyDate>
 <Track3:TrackID et:id='3' et:table='QuickTime::TrackHeader'>3</Track3:TrackID>
 <Track3:TrackDuration et:id='5' et:table='QuickTime::TrackHeader'>0:00:30</Track3:TrackDuration>
 <Track3:TrackLayer et:id='8' et:table='QuickTime::TrackHeader'>0</Track3:TrackLayer>
 <Track3:TrackVolume et:id='9' et:table='QuickTime::TrackHeader'>0.00%</Track3:TrackVolume>
 <Track3:MatrixStructure et:id='10' et:table='QuickTime::TrackHeader'>1 0 0 0 1 0 0 0 1</Track3:MatrixStructure>
 <Track3:MediaHeaderVersion et:id='0' et:table='QuickTime::MediaHeader'>0</Track3:MediaHeaderVersion>
 <Track3:MediaCreateDate et:id='1' et:table='QuickTime::MediaHeader'>2023:11:21 02:27:40</Track3:MediaCreateDate>
 <Track3:MediaModifyDate et:id='2' et:table='QuickTime::MediaHeader'>2023:11:21 02:27:40</Track3:MediaModifyDate>
 <Track3:MediaTimeScale et:id='3' et:table='QuickTime::MediaHeader'>1000</Track3:MediaTimeScale>
 <Track3:MediaDuration et:id='4' et:table='QuickTime::MediaHeader'>0:00:30</Track3:MediaDuration>
 <Track3:MediaLanguageCode et:id='5' et:table='QuickTime::MediaHeader'>und</Track3:MediaLanguageCode>
 <Track3:HandlerType et:id='8' et:table='QuickTime::Handler'>Text</Track3:HandlerType>
 <Track3:GenMediaVersion et:id='0' et:table='QuickTime::GenMediaInfo'>0</Track3:GenMediaVersion>
 <Track3:GenFlags et:id='1' et:table='QuickTime::GenMediaInfo'>0 0 0</Track3:GenFlags>
 <Track3:GenGraphicsMode et:id='4' et:table='QuickTime::GenMediaInfo'>ditherCopy</Track3:GenGraphicsMode>
 <Track3:GenOpColor et:id='6' et:table='QuickTime::GenMediaInfo'>32768 32768 32768</Track3:GenOpColor>
 <Track3:GenBalance et:id='12' et:table='QuickTime::GenMediaInfo'>0</Track3:GenBalance>
 <Track3:OtherFormat et:id='4' et:table='QuickTime::OtherSampleDesc'>text</Track3:OtherFormat>
 <Track3:Warning et:id='Warning' et:table='Extra'>[minor] The ExtractEmbedded option may find more tags in the media data</Track3:Warning>
 <Composite:ImageSize et:id='Exif-ImageSize' et:table='Composite'>480x270</Composite:ImageSize>
 <Composite:Megapixels et:id='Exif-Megapixels' et:table='Composite'>0.130</Composite:Megapixels>
 <Composite:AvgBitrate et:id='QuickTime-AvgBitrate' et:table='Composite'>408 kbps</Composite:AvgBitrate>
 <Composite:Rotation et:id='QuickTime-Rotation' et:table='Composite'>0</Composite:Rotation>
</rdf:Description>
</rdf:RDF>

MetaX is the utility I routinely use to manually edit metadata in video files. So most of my files are in whatever format it uses.

Ultimately the only thing I care about is that the Actors/Cast info can added systematically and then be read by Plex Media Server. If there is a different/easier/better method to add it using ExifTool, I'm all for it. If I have to make a template and modify it to my needs, no problem, sed to the rescue. If I can somehow edit .ExifTool_config to make it even easier I'll jump up and down with joy.

StarGeek

As long as the file isn't sensitive, you can use https://wormhole.app/  Drag file onto the browser and it gives you an url to download.  After 24 hours the file is deleted.

I wouldn't pass sensitive data as there is no idea about its privacy. But for stuff that you don't care about, it works pretty well.
"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

bcurran3

Sorry it took me so long to get back to you. Here it is:
https://wormhole.app/Rlvo6#GxiQkfsXZb0ZrQx7ERYvDA

StarGeek

Unfortunately, it wasn't as I had hoped.  Phil will have to take a look and see if this is something that can be added via config file or in the code.  He's away until next week though.  I'll keep the file on hand until then as that link dies in 24 hours.

Do you know what program added this XML:Cast in the first place?
"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

bcurran3

Thanks for trying.

I know Phil can do it if he wants to! (Start chanting: Go! Go! Go! Go!)

Yes. MetaX:
https://www.danhinsley.com/metax/metax.html

StarGeek

Unfortunately, it looks like I saved the file in my temp work directory which gets deleted from time to time. If you can repost the video, that would be helpful.
"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

Phil Harvey

I'll take a look if you can re-post the video.

- 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 found an example on the MetaX website
https://www.danhinsley.com/downloads/MetaXExample.mp4

C:\>exiftool -G1 -a -s -e -xml:all Y:\Sabnzbd\Completed\MetaXExample.mp4
[XML]           Directors                       : Stuart Rosenberg
[XML]           Producers                       : Gordon Carroll, Carter De Haven Jr.
[XML]           Screenwriters                   : Frank Pierson, Donn Pearce
[XML]           Studio                          : Jalem Productions

I think a config file, if possible, would be the best option for this, since this is the first time this has come up.  Taking a quick look at the example file, it writes all the data to standard Quicktime locations, as well as the Microsoft specific ones.  The XML seems to be only for use with the MetaX program.
"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

Phil Harvey

Unfortunately, writing these iTunesInfo tags requires more than just a config file.  And the XML tags are stored one level deeper than that (in plist-format XML inside an iTunesInfo iTunMOVI atom).

I don't know why Apple buries these tags so deeply, but luckily there hasn't been much need to write these up until now because there would be significant work involved to add this ability.

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

bcurran3

So is this a lost cause or a sit and wait?

Phil Harvey

The only hope is if you can find some other utility to write this.

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