8

I am trying to set up a script that will loop over a set of directories, and do one thing when it finds .jpg files, and another when it finds .nef files. The problem is, if a directory does not have .jpg files for example (or .nef) then the glob entry is no longer an expanded glob, but just a string. For example:

my_dir="pictures/"
ext="JPG"
for f in "$my_dir"*."$ext"; do
    echo $f
done

if the my_dir folder has .JPG files in it, then they will be echoed correctly on the command line.

pictures/one.JPG
pictures/two.JPG

However, if my_dir has no .JPG files, then the loop will enter for one iteration and echo:

pictures/*.JPG

how do I construct this so that if the glob has no matches, it does not enter the for loop?

15

This is normal and default behavior: If globbing fails to match any files/directories, the original globbing character will be preserved.

If you want to get back an empty result instead, you can set the nullglob option in your script as follows:

$ shopt -s nullglob
$ for f in "$my_dir"*."$ext"; do echo $f; done
$

You can disable it afterwards with:

$ shopt -u nullglob
5

Stepping a bit sideways, using find might also be useful here if the command you are running for the files is simple enough to drop on one line. Find can take several paths to look in, and will happily find any files in subdirectories too.

$ find foo/ bar/ -name "*.jpg" -exec echo {} \;
foo/ccc.jpg
foo/bbb.jpg
bar/aaa.jpg

(The command executed is given after the -exec flag, ending with the ;. {} gets replaced by the name of the current file.)

1

add this line to the start of your script

shopt -s nullglob

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.