当我循环遍历以 foo
开头的所有文件时,我会
for f in foo* ; do echo "result = $f" ; done
问题在于当foo
开头的没有文件时,我会得到以下错误:
当foo
开头的没有文件时,我会遇到问题:
result = foo*
这意味着即使没有以foo
开头的文件,循环也会执行一次。
为什么会这样?我该如何遍历所有文件(如果没有文件就不遍历)?
shopt -s nullglob
来自链接页面:
nullglob
是Bash shell选项,它修改[[glob]]扩展,使匹配不到文件的模式扩展为零个参数,而不是它们本身。
您可以使用-u
(取消设置,而s
是用于设置)来删除此设置:
shopt -u nullglob
$ touch foo1 foo2 foo3
$ for file in foo*; do echo "$file"; done
foo1
foo2
foo3
$ rm foo*
让我们看一看:
$ for file in foo*; do echo "$file"; done
foo*
设置 nullglob
:
$ shopt -s nullglob
$ for file in foo*; do echo "$file"; done
$
然后我们禁用该行为:
$ shopt -u nullglob
$ for file in foo*; do echo "$file"; done
foo*
如果不能或不想使用 nullglob
,标准做法是简单地检查文件是否存在。
for file in foo*; do
[ -f "$file" ] || continue
...
done
检查每个$file
的开销是必要的,因为如果$file
扩展为foo*
,你还不知道是否存在一个名为foo*
的文件(因为它匹配了模式),或者模式未能匹配并扩展为自身。当然,使用nullglob
可以消除这种歧义,因为失败的扩展不会产生任何参数,循环本身也不执行其主体。