ExifTool Forum

ExifTool => Newbies => Topic started by: Michael Meyer on February 28, 2012, 07:48:53 PM

Title: ExifTool from bash script
Post by: Michael Meyer on February 28, 2012, 07:48:53 PM
I have written a bash script that will iterate incoming arguments, build a set of keywords to update and execute ExifTool to update an image.

I am having problems with ExifTool interpreting the arguments passed to it.

I have extracted the gist of what I am doing into a simplified bash script.

Executing ExifTool from within the script fails, it seems to interpret the argument differently. 
Echoing to sh seems to work.
Copying the echo output and pasting into terminal also works.

If the Subject has no spaces it works fine.

I am getting errors:
Error: File not found - Village"
Error: File not found - Arnold"

I'm baffled, is this some shell esoterica or a problem with the ExifTool wrapper script.

setsubjects
=======
#!/usr/bin/env bash

filename=test123.jpg
allsubj="-xmp-dc:Subject+=\"Places|Europe|Germany|Small Village\" -xmp-dc:Subject+=\"People|Meyer|Georg Arnold\""

# This works
echo exiftool -overwrite_original ${allsubj} ${filename} | sh

# This does not work
exiftool -overwrite_original ${allsubj} ${filename}

# echo shows the right thing, copy output, paste into terminal works
echo exiftool -overwrite_original ${allsubj} ${filename}

Title: Re: ExifTool from bash script
Post by: Phil Harvey on February 28, 2012, 10:42:46 PM
Wow.  Tricky.

I haven't figured out the answer yet, but it is clear that the echo command suffers the same problem.  It appears the echo works, but it does not.  Change the space into more spaces to see what I mean:

allsubj="-xmp-dc:Subject+='Places|Europe|Germany|Small    Village'"

echo exiftool -overwrite_original ${allsubj} ${filename}


produces this:

exiftool -overwrite_original -xmp-dc:Subject+='Places|Europe|Germany|Small Village' a.jpg

I don't have time to think about this more now, but I will when I get a chance.

- Phil
Title: Re: ExifTool from bash script
Post by: Michael Meyer on February 28, 2012, 11:38:40 PM
I ran the script with bash -x and saw the differences in the echo statements below


#!/usr/bin/env bash -x

filename='test123.jpg'
allsubj="-xmp-dc:Subject+=\"Places|Europe|Germany|Small  Village\" -xmp-dc:Subject+=\"People|Meyer|Georg  Arnold\""

echo "${allsubj}"

echo ${allsubj}


The echo with the quotes executes as:  note has the 2 spaces preserved:

+ echo '-xmp-dc:Subject+="Places|Europe|Germany|Small  Village" -xmp-dc:Subject+="People|Meyer|Georg  Arnold"'


without quotes, bash interprets the var as:

+ echo '-xmp-dc:Subject+="Places|Europe|Germany|Small' 'Village"' '-xmp-dc:Subject+="People|Meyer|Georg' 'Arnold"'


Strange, I'll add quotes around my variable.

Thanks,
Title: Re: ExifTool from bash script
Post by: Michael Meyer on February 29, 2012, 12:42:30 AM
Hmmm, still not right.  I noticed that in the first one the string is passed in as one parameter, resulting in setting the xmp subject to include the command.



+ exiftool -overwrite_original '-xmp-dc:Subject+="Places|Europe|Germany|Small  Village" -xmp-dc:Subject+="People|Meyer|Georg  Arnold"' test123.jpg


Resulting subject:

exiftool -G -s -subject test123.jpg
[XMP]           Subject                         : "Places|Europe|Germany|Small  Village" -xmp-dc:Subject+="People|Meyer|Georg  Arnold"
Title: Re: ExifTool from bash script
Post by: Phil Harvey on February 29, 2012, 09:27:29 AM
OK, here is the solution:

#!/bin/sh
filename='test123.jpg'
allsubj="-xmp-dc:Subject+=Places|Europe|Germany|Small Village"
exiftool -overwrite_original "${allsubj}" "${filename}"


I've used /bin/sh here, but bash should work too (/bin/sh is smaller and lighter though, so the preferred shell for scripts).

The problem is that the shell strips one level of quotes when assigning "allsubj", but apparently doesn't strip quotes from within a shell variable after interpolating the value within a command line... which makes sense now that I think about it.  So you must add quotes around the variables in the command instead.

- Phil
Title: Re: ExifTool from bash script
Post by: Alan Clifford on February 29, 2012, 10:01:24 AM
Phil, that still doesn't work with

allsubj="-xmp-dc:Subject+=Places|Europe|Germany|Small Village -xmp-dc:Subject+=People|Meyer|Georg"


You get
Subject: Places|Europe|Germany|Small Village -xmp-dc:Subject+=People|Meyer|Georg
Title: Re: ExifTool from bash script
Post by: Michael Meyer on February 29, 2012, 12:46:28 PM
I rewrote the script to use an array instead of concatenated strings, seems to work better.


#!/usr/bin/env sh -x

filename='test123.jpg'

# collect subjects as an array
allsubj[0]="-xmp-dc:Subject+=\"Places|Europe|Germany|Small  Village\""
allsubj[1]="-xmp-dc:Subject+=\"People|Meyer|Georg  Arnold\""

# clear subject
exiftool -q -overwrite_original -xmp-dc:Subject= ${filename}

# This works with array
exiftool -q -overwrite_original "${allsubj[@]}" ${filename}

# Check if it worked
exiftool -G -s -xmp:subject ${filename}


The shell debug output shows that the array expands to one argument per array element, and retains the extra spaces in the subject values:

+ filename=test123.jpg
+ allsubj[0]='-xmp-dc:Subject+="Places|Europe|Germany|Small  Village"'
+ allsubj[1]='-xmp-dc:Subject+="People|Meyer|Georg  Arnold"'
+ exiftool -q -overwrite_original -xmp-dc:Subject= test123.jpg
+ exiftool -q -overwrite_original '-xmp-dc:Subject+="Places|Europe|Germany|Small  Village"' '-xmp-dc:Subject+="People|Meyer|Georg  Arnold"' test123.jpg
+ exiftool -G -s -xmp:subject test123.jpg


and the subject written into the xmp shows as 2 elements instead of the previous one concatenated string:

[XMP]           Subject                         : "Places|Europe|Germany|Small  Village", "People|Meyer|Georg  Arnold"



FYI, in my actual script I have this as a function:

#!/usr/bin/env sh

function setSubject {
filename=$1
shift

declare -a allsubj
index=0
while [ $# -ne 0 ]; do
allsubj[index]="-xmp-dc:Subject+=\"$1\""

((index++))
shift
done

if [ ${#allsubj[@]} -ne 0 ]; then
exiftool -q -overwrite_original "${allsubj[@]}" ${filename}
fi
}

# test it
setSubject test123.jpg "Places|Europe|Germany|Small  Village" "People|Meyer|Georg  Arnold"
exiftool -G -S -Subject -HierarchicalSubject test123.jpg


Thanks all,
Title: Re: ExifTool from bash script
Post by: Phil Harvey on February 29, 2012, 01:24:04 PM
Right.  Definitely trickier to have 2 command-line arguments in the same shell variable.

I've never used an interpolated array like this in shell scripting, so you've taught me something.  Smart.

- Phil
Title: Re: ExifTool from bash script
Post by: Michael Meyer on March 01, 2012, 01:41:40 PM
After some more ExitTool doc reading I could also have collected the just the keywords in a delimited string, with a few extra quotes and escaped quotes:


#!/usr/bin/env sh -x

filename='test123.jpg'

# collect subjects
subj1="Places|Europe|Germany|Small  Village"
subj2="People|Meyer|Georg  Arnold"

allsubj="${subj1}//${subj2}"

exiftool -q -overwrite_original -sep "//" -xmp-dc:Subject=\""${allsubj}"\" ${filename}


Enough fun, back to work.   :)

Title: Re: ExifTool from bash script
Post by: brambil on January 22, 2021, 03:58:34 PM
Hallo to all.

I know is necroposting, but I have the some trouble.

The script returns file not found, but if I execute the command as reported in error copying and pasting in the terminal line it works.

Is the problem still here?

echo "exiftool -p -Keywords=\"${keyword}\" -Title+=\"ERA: ${fname}\" $fname -overwrite_original" | bash
could be a good solution?

And to do this any idea or better solution?
(I try to set the date, if it works (=no Datetimeoriginal was set)go on, otherwise maybe I want to overwrite it.


"exiftool -wm cg -DateTimeOriginal=\"${anno}':01:01 00:00:00'\" -overwrite_original ${fname}"
if [ $? -ne 0 ] #non avevo già una data e l'ho messa
then
datafile=(echo "exiftool -s3 -createdate \"$fname\"") | bash
while true
do
if [ "$anno" -lt 2021 ] #la scrittura della data in EXIF la faccio solo se è un anno minore di 2021. Se ho messo 5060 per indicare anni 50-60 non lo metto
then
read -e -p "Sovrascrivere la data $datafile con $anno?[Yes/No/Vuoto]" -i "Y" yn </dev/tty
else
read -e -p "Sovrascrivere la data $datafile con $anno?[Yes/No/Vuoto]" -i "N" yn </dev/tty
fi
case $yn in
[Yy]* ) echo "exiftool -p -DateTimeOriginal=\"${anno}':01:01 00:00:00'\" -overwrite_original \"${fname}\"" | bash;break;;
[Nn]* ) break;; #Non fo una sega
[0123456789][0123456789][0123456789][0123456789]* ) $("exiftool -p -DateTimeOriginal=\"${yn}:01:01 00:00:00\" -overwrite_original \"${fname}\"");break;;
* ) echo "Inserire Y[es]/N[o] o l'anno";;
esac
done
fi


The problem is also with 12.16

Thanks.