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
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*
source to share
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.
source to share