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

+4


source to share


2 answers


You can stop this behavior by setting nullglob :

shopt -s nullglob

      

From the linked page:

nullglob

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

      

Test



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

      

We'll see:

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

      

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
foo*

      

+7


source


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

      



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.

+4


source







All Articles