21

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?

Vince W.
  • 333

3 Answers3

31

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
joepd
  • 2,397
7

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

ilkkachu
  • 138,973
4

add this line to the start of your script

shopt -s nullglob
steve
  • 21,892