当我循环遍历以foo
开始的所有文件时,我执行
for f in foo* ; do echo "result = $f" ; done
问题是当没有文件通过foo
启动时,我得到:
result = foo*
这意味着即使没有文件由foo
启动,循环也会执行一次。
这怎么可能?如何循环浏览所有文件(如果没有文件,则完全不循环)?
您可以通过设置nullglob:来停止这种行为
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
可以消除这种模糊性,因为失败的扩展不会产生任何参数,循环本身也不会执行主体。