当没有匹配的文件时,如何跳过for循环?

18

当我循环遍历以 foo 开头的所有文件时,我会

for f in foo* ; do echo "result = $f" ; done

问题在于当foo开头的没有文件时,我会得到以下错误:

Translated text:

foo开头的没有文件时,我会遇到问题:

result = foo*

这意味着即使没有以foo开头的文件,循环也会执行一次。

为什么会这样?我该如何遍历所有文件(如果没有文件就不遍历)?


可能是 bash loop over file mask 的重复问题。 - cnst
2个回答

20
你可以通过设置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*

12

如果不能或不想使用 nullglob,标准做法是简单地检查文件是否存在。

for file in foo*; do
    [ -f "$file" ] || continue
    ...
done

检查每个$file的开销是必要的,因为如果$file扩展为foo*,你还不知道是否存在一个名为foo*的文件(因为它匹配了模式),或者模式未能匹配并扩展为自身。当然,使用nullglob可以消除这种歧义,因为失败的扩展不会产生任何参数,循环本身也不执行其主体。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接