【问题标题】:How to skip the for loop when there are no matching files?没有匹配的文件时如何跳过for循环?
【发布时间】:2014-12-03 01:09:43
【问题描述】:
当我遍历所有以foo 开头的文件时,我会这样做
for f in foo* ; do echo "result = $f" ; done
问题是当 没有文件 以foo 开头时,我得到:
result = foo*
意味着循环执行一次,即使没有以foo开头的文件。
这怎么可能?如何循环遍历所有文件(如果没有文件则根本不循环)?
【问题讨论】:
标签:
bash
for-loop
wildcard
shopt
【解决方案1】:
你可以通过设置nullglob来阻止这种行为:
shopt -s nullglob
来自链接页面:
nullglob 是一个修改 [[glob]] 扩展的 Bash shell 选项
使得不匹配文件的模式扩展到零参数,
而不是自己。
您可以使用-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*
【解决方案2】:
执行此操作的标准方法(如果您不能或不想使用nullglob)是简单地检查文件是否存在。
for file in foo*; do
[ -f "$file" ] || continue
...
done
检查$file 的每个值的开销是必要的,因为如果$file 扩展为foo*,您还不知道是否真的存在一个名为foo* 的文件(因为它匹配模式)或者如果模式无法匹配并扩展到自身。当然,使用nullglob 可以消除这种歧义,因为失败的扩展不会产生任何参数,并且循环本身也不会执行主体。