ExifTool Forum

ExifTool => Developers => Topic started by: Joanna Carter on May 30, 2021, 08:24:54 AM

Title: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on May 30, 2021, 08:24:54 AM
It's me again  ;)

In trying to optimise the number of commands I am executing, I'm trying to enumerate a list of urls, which can be either image files or xmp files, using the same code.

So, I need to detect whether the source file is a RAW file or not. I'm using this command to test...

exiftool -if '$fileType eq "NEF"' -tagsfromfile JNA_0052.NEF "-format<mimetype" JNA_0052.xmp

It always fails, no matter what file extension I put in the condition. Any ideas please?
Title: Re: Conditionally write to XMP file based on type of source file
Post by: StarGeek on May 30, 2021, 11:16:10 AM
You're processing an XMP file.  That Filetype will never equal NEF and always be Filetype eq "XMP".
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on May 30, 2021, 03:15:40 PM
Even if I replace NEF with XMP, it still fails the condition.

I have an array of files which can be either RAW or XMP. What I am trying to do is to transfer two tags from the NEF (or other RAW file) to the XMP file, but only if the "source" file is a RAW file.

Can you help with the correct syntax?
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on May 31, 2021, 05:57:04 PM
So, can anyone help with this?

To clarify what I'm after...

1. I have a list of files that can be either NEF or XMP.
2. I want to process them in such a way that, if the file is NEF, an XMP file with the same name should be either created and/or written to with two tags copied from the NEF file.

Helllppp!!!  :o ::)
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Phil Harvey on May 31, 2021, 09:03:51 PM
See Example 13 here (https://exiftool.org/metafiles.html#EX13), and add as many -ext options as you want for the various raw files you want to process.

- Phil
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on June 01, 2021, 03:40:38 AM
Quote from: Phil Harvey on May 31, 2021, 09:03:51 PM
See Example 13 here (https://exiftool.org/metafiles.html#EX13), and add as many -ext options as you want for the various raw files you want to process.
Thank you for that lead but I don't want to process a whole directory, just a list of files that I am generating in code.

Is that possible with one command per file?
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Phil Harvey on June 01, 2021, 06:36:55 AM
You just put whatever files/directories you want to process on the command line.

Doing one command per file is much slower.  You can put as many file names on the command line as you want.  (There is a command-line-length limitation, and if you are getting close to that you should use the -@ option and put the file names in an argfile.)

- Phil
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on June 01, 2021, 10:38:05 AM
Thank you once again. Most of the time I am only dealing with writing to one file at a time; it just depends on how many images the user selects in the software but it would be rare to select a whole directory.

So, for unconditional code, am I right in saying that my code should be creating these (or more) "arguments"?


-xmp:subject=Didier JNA_0052.NEF
-tagsfromfile JNA_0052.NEF "-xmp:subject<xmp:subject" "-SidecarForExtension<filetype" "-format<mimetype" JNA_0052.xmp
-api compact=onedesc


What I now want to do is execute the second two lines only if the first line applies to a RAW file, hence my idea of the -if '$filetype eq "NEF"' to test the file type of the source file but that seems to test the target file instead.
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on June 01, 2021, 01:18:32 PM
My software searches for keywords, which could be found either in a standalone RAW file or in a related sidecar. If the search returns the URL of an XMP file, I then need to get back to the RAW file in order to show its thumbnail instead of an icon for the RAW file.

This whole effort is all about the faint possibility of having more than one RAW file type, with the same name, in the same directory and trying to avoid writing to an XMP file for the wrong RAW file.

I know it is not normal to have more than one RAW file with the same name because of just such confusion. But it is still possible that someone could add a second RAW file after the XMP has been written for the first.



It might seem unlikely but I feel I should cover the eventuality.
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Alan Clifford on June 01, 2021, 02:40:26 PM
Quote from: Joanna Carter on June 01, 2021, 01:18:32 PM

This whole effort is all about the faint possibility of having more than one RAW file type, with the same name, in the same directory and trying to avoid writing to an XMP file for the wrong RAW file.


Can't you name your xmp files as

myphotosname.nef.xmp
myphotosname.nrw.xmp


Title: Re: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on June 01, 2021, 02:52:35 PM
Quote from: Alan Clifford on June 01, 2021, 02:40:26 PM
Can't you name your xmp files as

myphotosname.nef.xmp
myphotosname.nrw.xmp
If they were my files, yes. But this app is for photographers who already have their EXIF data in XMP files. It us my job to be provide a search facility that looks into their files, whether they be RAW or XMP and, if they are XMP files find the RAW file that it is based on
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Phil Harvey on June 02, 2021, 06:54:19 AM
Quote from: Joanna Carter on June 01, 2021, 10:38:05 AM
So, for unconditional code, am I right in saying that my code should be creating these (or more) "arguments"?


-xmp:subject=Didier JNA_0052.NEF
-tagsfromfile JNA_0052.NEF "-xmp:subject<xmp:subject" "-SidecarForExtension<filetype" "-format<mimetype" JNA_0052.xmp
-api compact=onedesc


What I now want to do is execute the second two lines only if the first line applies to a RAW file, hence my idea of the -if '$filetype eq "NEF"' to test the file type of the source file but that seems to test the target file instead.

Try this.  (I list the arguments in -@ argfile format):

-xmp:subject=Didier
JNA_0052.NEF
-ext
nef
-ext
cr2
-ext
arw
... (all the raw extensions you support)
-execute
-if
$ok
-tagsfromfile
JNA_0052.NEF
-xmp:subject<xmp:subject
-SidecarForExtension<filetype
-format<mimetype
JNA_0052.xmp
-api
compact=onedesc


- Phil

Edit: forgot newline after -api
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on June 03, 2021, 03:23:41 AM
Wow! Almost  :D

Since your reply, I have realised that I really shouldn't be writing anything to the RAW file if the user has chosen to use XMP files.

So, now I end up with...


-xmp:subject=Didier JNA_0052.xmp
-tagsfromfile JNA_0052.NEF "-SidecarForExtension<filetype" "-format<mimetype" JNA_0052.xmp
-api compact=onedesc


... to write the subject to the XMP file followed by copying the tags from the RAW to the XMP file.

But I realise that this is actually two commands. Since I am now only concerned with writing to the XMP file, how do I best combine the two?
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on June 03, 2021, 03:30:19 AM
Aaaarrrgghhh!!!

Why do I have to think of the answer after posting an obvious error?

I now have...


-xmp:subject=Didier
-tagsfromfile JNA_0052.NEF "-SidecarForExtension<filetype" "-format<mimetype" JNA_0052.xmp
-api compact=onedesc


Which is exactly what I wanted, once I realised what I thought I wanted wasn't what I really wanted  :o ::) ???

Phil, thank you so much for taking the time and effort to help me figure this stuff out.
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on June 03, 2021, 08:40:36 AM
Well, thanks to your help, I now have the code I need for writing to an XMP file without needing to write to the RAW file as well, and setting the tags from the RAW file that I will need for searching.


    -preserve
    -ignoreMinorErrors
    -overwrite_original_in_place
    -mwg:keywords=Didier
    -tagsFromFile /Users/joannacarter/Pictures/JNA_0052.NEF '-SidecarForExtension<filetype'
    /Users/joannacarter/Pictures/JNA_0052.xmp


But, even though everything works, I am getting a minor warning peeking through...


Warning: No writable tags set from /Users/joannacarter/Pictures/JNA_0052.xmp


This doesn't happen from the command line

Any ideas?
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Phil Harvey on June 03, 2021, 08:59:16 AM
Hi Joanna,

Your warning message contradicts the command you say you are using.  The warning indicates you are copying tags from the XMP file.

Why are you placing the options on separate lines?  Are you using an argfile?  What is the exact command you are using?

- Phil
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on June 03, 2021, 11:21:29 AM
My apologies. I put the options on separate lines because that is how they are built in my software, one line per argument. They are all concatenated with one space between each argument when the command is about to be executed.

The Process is set up in code like this...


  {
    let process = Process()
   
    process.executableURL = appURL
   
    process.arguments = theListOfArguments // as you see from my previous post
   
    ...

    process.launch()
  }


If I copy the command line I end up with...

exiftool -preserve -ignoreMinorErrors -overwrite_original_in_place -mwg:keywords=Didier -tagsFromFile /Users/joannacarter/Pictures/JNA_0052.NEF '-SidecarForExtension<filetype' /Users/joannacarter/Pictures/JNA_0052.xmp

And I end up with "    1 image files updated\n" being returned from the executing the process.
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Phil Harvey on June 03, 2021, 12:36:31 PM
OK.  So it works from the command line.  If it doesn't work from inside your app, then there is a difference in the way the arguments are parsed when you execute from within your app.  I can't help with this.

- Phil
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on June 03, 2021, 07:55:36 PM
I've resorted to hand-crafting minimised copying arguments to test this out, as this seems to be where the problem lies.


let args = ["-v5", "-tagsFromFile /Users/joannacarter/Pictures/JNA_0052.NEF", "'-SidecarForExtension<filetype'", "/Users/joannacarter/Pictures/JNA_0052.xmp"]


This generates the following errors...


Invalid TAG name: "tagsFromFile /Users/joannacarter/Pictures/JNA_0052.NEF"
Error: File not found - '-SidecarForExtension<filetype'
Warning: Invalid tag name 'tagsFromFile /Users/joannacarter/Pictures/JNA_0052.NEF' - /Users/joannacarter/Pictures/JNA_0052.xmp


If I run the command in Terminal, I get a v5 output of...


Setting new values from /Users/joannacarter/Pictures/JNA_0052.NEF
Writing XMP-photoshop:SidecarForExtension
======== /Users/joannacarter/Pictures/JNA_0052.xmp
Rewriting /Users/joannacarter/Pictures/JNA_0052.xmp...
  FileType = XMP
  FileTypeExtension = XMP
  MIMEType = application/rdf+xml
    - XMP-photoshop:SidecarForExtension = 'NEF'
    + XMP-photoshop:SidecarForExtension = 'NEF'
    1 image files updated


For my generated args, am I splitting them in the wrong place?
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Phil Harvey on June 03, 2021, 07:59:13 PM
Yes
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on June 04, 2021, 03:31:16 AM
What kind of an answer is that?  :P ::)

As it happens, a good one but I was too tired to continue last night (didn't hit the sack until 2am)

Anyway, with a bit if persistence, here's the final arguments list...


    -preserve
    -ignoreMinorErrors
    -overwrite_original_in_place
    -mwg:keywords=Didier
    -tagsFromFile
    /Users/joannacarter/Pictures/JNA_0052.NEF
    -SidecarForExtension<filetype
    -format<mimetype
    /Users/joannacarter/Pictures/JNA_0052.xmp


One of the problems was that, in Terminal, you need to surround the copy arguments with single quotes, so I dutifully added them in to my generating code. I was also under the impression from the documentation (yes I have read it  ;) ) that the -tagsFromFile argument included the source filename, which is what led me to concatenate them in my generating code.

Now, the Swift code to generate a -TagsFromFile "phrase" is simply...


let tagsFromFileArgument = ExifCommand.Argument.tagsFromFile(sourceFilename: sourceFilename,
                                                                             destinationArguments: [.sidecarForExtension, .format],
                                                                             sourceArguments: [.fileType, .mimeType])


Thanks once again for your forbearance with an old girl still learning new tricks after thirty years in the game  8)
Title: Re: Conditionally write to XMP file based on type of source file
Post by: Joanna Carter on June 04, 2021, 12:38:37 PM
I just had to come on here and celebrate having got everything (so far) to work.

I can now write the same metadata to a RAW file and/or an XMP file, in any combination!

Here's the argument list for writing a keyword to both, all in one command...


  -preserve
  -ignoreMinorErrors
  -overwrite_original_in_place
  -mwg:keywords=Drill
  /Users/joannacarter/Pictures/JNA_0052.NEF
  -all=
  -tagsFromFile
  /Users/joannacarter/Pictures/JNA_0052.NEF
  -all
  -filetype>SidecarForExtension
  -mimetype>format
  -mwg:keywords=Drill
  /Users/joannacarter/Pictures/JNA_0052.xmp


This also takes care of the possibility of having two RAW files with the same name in the same directory. Last one written to rewrites the XMP file. Not a perfect solution but even the great Adobe can't do better.

I leave this message in appreciation of all the help I have received here and as searchable material for those who might have need to solve the same problem