问题
When I loop through all the files starting by foo I do
for f in foo* ; do echo "result = $f" ; done
The problem is when no file start by foo I get:
result = foo*
Meaning that the loop is executed once, even if no file start by foo.
How is this possible? How can I loop through all files (and not loop at all if there is no file)?
回答1:
You can stop this behaviour by setting nullglob:
shopt -s nullglob
From the linked page:
nullglobis a Bash shell option which modifies [[glob]] expansion such that patterns that match no files expand to zero arguments, rather than to themselves.
You can remove this setting with -u (unset, whereas s is for set):
shopt -u nullglob
Test
$ touch foo1 foo2 foo3
$ for file in foo*; do echo "$file"; done
foo1
foo2
foo3
$ rm foo*
Let's 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 disable the behaviour:
$ shopt -u nullglob
$ for file in foo*; do echo "$file"; done
foo*
回答2:
The standard way to do this (if you can't or don't want to use nullglob) is to simply check if the file exists.
for file in foo*; do
[ -f "$file" ] || continue
...
done
The overhead of checking each value of $file is necessary because if $file expands to foo*, you don't yet know if there actually was a file named foo* (because it matches the pattern) or if the pattern failed to match and expanded to itself. Using nullglob, of course, removes that ambiguity because a failed expansion produces no arguments and the loop itself never executes the body.
来源:https://stackoverflow.com/questions/26255799/how-to-skip-the-for-loop-when-there-are-no-matching-files