shell 为什么在Bash中不默认nullglob行为?

jv2fixgn  于 2022-11-30  发布在  Shell
关注(0)|答案(1)|浏览(248)

我最近需要使用一个Bash for循环来递归遍历目录中的几个文件:

for video in **/*.{mkv,mp4,webm}; do
  echo "$video"
done

在花费了大量时间进行调试之后,我意识到即使模式不匹配,循环也会运行,从而导致:

file1.mkv
file2.mp4
**/*.webm # literal pattern printed when no .webm files can be found

一些详细的搜索最终发现这是known behaviour in Bash,对于它,使用shopt -s nullglob启用shell的nullglob选项是解决方案。
是否有理由认为这种违反直觉的行为是默认的,需要使用nullglob显式禁用,而不是相反?或者换一种方式问,总是启用nullglob是否有任何缺点?

y3bcpkx1

y3bcpkx11#

man 7 glob开始:

    • 空列表**

上面给出了一个简单的规则:"将通配符模式扩展到匹配路径名的列表中"是UNIX的原始定义。它允许将模式扩展到空列表中,如

xv -wait 0 *.gif *.jpg

其中可能不存在 *. gif文件(这不是错误)。但是,POSIX要求通配符模式在语法不正确或匹配路径名列表为空时保持不变。使用 * bash *,可以使用以下命令强制执行经典行为:

shopt -s nullglob

(类似的问题也会发生在其他地方。例如,旧的指令码

rm `find . -name "*~"`

新脚本需要

rm -f nosuchfile `find . -name "*~"`

以避免使用空参数列表调用 * rm * 时出现错误消息。)
简而言之,它是POSIX兼容所需的行为。
当然,你现在可以问POSIX指定这种行为的基本原理是什么。

相关问题