I am having issues when trying to return the one image file that fits the parameters. $1 is the search parameter, in this incident it is "real" which is a tag on one of the images (not two) in the given folder. What happens when I call it "./test.sh real" is it prints off both images, rather than just the one. I imagine it has to deal with me setting up the function return as a variable and/or my condition statement, but I am not quite sure.

for f in specim/*.jpg
    image=$(exiftool -EXIF:XPKeywords $f | grep "$1")
    if [[ !  -z  "$image// }"  ]]; then
    echo $f

what's returned:

../../test.sh real

This bash script prints off what I want, only the one image rather than both (as the exiftool stuff which I don't want, but this was just a test):

for f in *.jpg
    exiftool -EXIF:XPKeywords $f | grep $1


./test2.sh real
XP Keywords                     : name;real

any help would be appreciated and it's probably super simple... Thanks

  • 1
    "$image// }" looks like a typo for "${image// }" – Toby Speight Sep 24 '15 at 6:51

It is probably as you suspected, just a minor change to fix, try instead:

if [[ !  -z  "$image"  ]]; then


Let's say when there is a match by exiftool and grep, then your $image variable contains this:


But when there is no output, $image contains: (nothing)

In your test condition, you had:

if [[ !  -z  "$image// }"  ]]; then

So, in the first case bash sees this:

if [[ !  -z  "abcabcabc// }"  ]]; then

But in the second case, bash sees this:

if [[ !  -z  "// }"  ]]; then

The test is saying if "// }" is NOT zero-value, then... however "// }" is always going to be not zero value, it is something, it is a string consisting of two slashes a space and a curly brace. So since there is something there, something not zero-value, that is why the then part is triggered even when you have no matches in $image. So by removing this // } it should work.


Another option might be:

if [[ -n "$image" ]]; then

to check whether only the $image variable contains something, rather than ! -z ...


You are running exiftool and grep (+ a test and echo) for each .jpg in that directory... not very efficient...
exiftool can do all that by itself via the -if EXPR option, e.g.

exiftool -q -s3 -if '$tag=~/pattern/' -filename ./*.jpg

(here combined with -q - quiet and -s[NUM] - short output format: print values only, see the manual for more details)
So, in your particular case the whole script could be replaced by:

exiftool -q -s3 -if \$Exif:XPKeywords=~/"$1"/ -filename specim/*.jpg

e.g. running the test.sh script with four test files that have the following XPKeywords values:

exiftool -Exif:XPKeywords specim/*.jpg
======== specim/1.jpg
XP Keywords                     : xname;real
======== specim/2.jpg
XP Keywords                     : yname;different
======== specim/3.jpg
XP Keywords                     : wname;true
======== specim/4.jpg
XP Keywords                     : wname;unreal
    4 image files read

running test.sh real returns:


and test.sh unreal returns:


grep's exit status is whether or not it matched something, so why capture grep's output and then test it, as a string, for emptiness? You could do

if exiftool -EXIF:XPKeywords $f | grep -q "$1" ; then
    echo $f

if you wanted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.