当我遍历所有从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
当然,使用可以消除这种歧义,因为失败的扩展不会产生任何参数,并且循环本身永远不会执行主体。