How can I skip the for loop when there are no matching files?

When I go through all the files starting with foo

I do

for f in foo* ; do echo "result = $f" ; done


The problem is, when I run the file, foo

I don't get:

result = foo*


Meaning that the loop is executed once, even if the file does not start with foo


How is this possible? How can I loop through all files (and not loop at all if there is no file)?


source to share

2 answers

You can stop this behavior by setting nullglob :

shopt -s nullglob


From the linked page:


is a Bash shell option that changes the [[glob]] extension so that patterns that don't match any files are expanded to null arguments, not themselves.

You can remove this setting with -u

(unset, whereas s

for set):

shopt -u nullglob



$ touch foo1 foo2 foo3
$ for file in foo*; do echo "$file"; done
$ rm foo*


We'll see:

$ for file in foo*; do echo "$file"; done


Setting nullglob


$ shopt -s nullglob
$ for file in foo*; do echo "$file"; done


And then we'll disable the behavior:

$ shopt -u nullglob
$ for file in foo*; do echo "$file"; done




The standard way to do this (if you can't or don't want to use it nullglob

) is to simply check if the file exists.

for file in foo*; do
    [ -f "$file" ] || continue


The overhead of checking each value is $file

necessary because if it $file

expands to foo*

, you still don't know if there was actually a file named foo*

(since it matched the pattern) or if the pattern didn't match and expanded to itself. Usage nullglob

, of course, removes this ambiguity, because the failed expansion creates no arguments, and the loop itself never executes the body.



All Articles