Answers:
我期望没有任何输出。
如果nullglob
使用默认值,那么许多命令的行为将非常出乎意料,因为(很不幸),命令对待零文件名参数的情况的定性不同于一个或多个文件名参数的情况。
假设您已启用nullglob
(shopt -s nullglob
)并且位于没有文件匹配的目录中*.txt
。然后*.txt
确实会扩展为空-不是您期望的那样是一个空字段,但根本没有任何字段。但这将产生以下结果:
ls *.txt
会列出当前目录中的所有文件(隐藏文件除外),因为这是ls
当您不传递任何文件名参数时所做的。cat *.txt
将从标准输入读取,因为如果cat
没有文件名参数,就好像您在运行cat -
。如果以交互方式运行,它会等待输入。许多命令都以这种方式运行。cp *.txt dest/
会因错误而失败cp: missing destination file operand after 'dest/'
。这不是灾难,但是它很混乱,与可能期望的无声成功大不相同。file *.txt
,以及文件名参数为零的情况下没有特殊行为的其他各种程序,如果不传递任何内容,仍然会失败,并显示错误或用法消息。printf 'Got file: "%s"\n' *.txt
将打印Got file: ""
而不是什么。*
,?
和[
那不打算由外壳扩展将更加频繁产生明显错误的结果,但方式可能难以弄清楚。例如,如果当前目录中没有文件名以开头gedit
,则apt list gedit*
(apt list 'gedit*'
原意是)将变为正义apt list
并列出所有可用的软件包。因此,最好不要提出要求就不要这种行为。实际上可能被简化的最常见的实际情况nullglob
是for f in *.txt
。另请参阅此问题(Sergiy Kolodyazhnyy的答案与该问题相关联)。
较难回答的问题是,为什么failglob
bash中的默认值不是扩展名,即它与任何文件都不匹配是一个扩展错误。我相信Sergiy Kolodyazhnyy的答案即使没有直接解决也能抓住原因。保留未扩展的球体而不会产生扩展错误是(很不幸)是标准化的行为,也是传统的行为,因此也是预期的行为。尽管bash除非使用名称进行调用sh
或通过该--posix
选项,否则它不会尝试完全兼容POSIX ,但即使不是在POSIX模式下,它的许多设计选择也直接遵循POSIX。他们必须选择一些行为,并且有违背用户期望的缺点。
我认为这是该问题历史上影响最小的方面,因此我将其保留了下来……但是值得一提的是,nullglob
行为在概念上有些奇怪。
nullglob
乍一看似乎很优雅,因为在语法上,它对待零匹配文件的情况与一,二或任何其他数字的情况没有区别。这水珠扩展到论据,我们运行的命令,不倾向于把它们相同,上面详细介绍。但是从句法上讲,这至少是正确的,我认为这是提出问题的动机。
但是,还有另一个更细微的不一致nullglob
无法解决-它实际上在放大。的情况下,零名的通配符(“通配符”)是从一个或两个,或任何其他数量的处理过的深刻不同。例如,使用shopt -s nullglob
,如果ab?d?f
与任何文件都不匹配,则将其删除;否则,将其删除。如果ab?d
与任何文件都不匹配,则将其删除;但是如果ab
与任何文件都不匹配(即,如果没有名称完全相同的文件ab
),则仍不会删除该文件。当然,如果将其删除将是一个灾难,因为它可能根本不旨在引用当前目录中的现有文件。它甚至可能没有引用文件。但这仍然消除了实现整体一致性的希望。
bash提供了三种行为-默认情况下,将与任何文件都不匹配的glob视为不是glob,并将它们传递为未扩展状态,这是您期望对其进行处理的行为(如果您可以避免使用这种奇怪的短语)表示匹配的所有文件均为零(nullglob
),以及将其视为错误的安全行为(failglob
),都代表了不同的方法来解决shell固有的歧义性,从而无法知道是否有任何特定的单词打算用作文件名。Shell在执行扩展时不知道您使用它调用的特定命令将如何处理其参数。
这是关注点分离的许多实例之一。在其设计遵循Unix哲学的系统中,每个部分都旨在做一件事情,并且做得很好。Shell将文本处理为命令和参数,然后调用这些命令,其中大多数命令在Shell本身外部。与外部命令本身负责执行这些转换的系统(例如DOS和Windows中的传统命令处理器)相比,这往往会更好,更通用。但是它偶尔也有缺点。
failglob
。因此它不能成为默认值,因为并不总是支持它。
主要原因是因为这是POSIX指定的标准行为-该标准涵盖了shell命令语言以及其他模式匹配(shell,例如shell bash
,dash
shell-Ubuntu的默认语言/bin/sh
,并ksh
遵循此标准)。从第2.13.3节开始,用于文件名扩展的模式:
如果模式与任何现有的文件名或路径名都不匹配,则模式字符串应保持不变。
当然,这会产生副作用-匹配文件名,实际上可能是文件名*.txt
。该nullglob
选件bash
和zsh
可以帮助:如果该选项是通过支持shopt -s nullglob
(这不是默认它适用于这个问题启用),然后globstar将扩大到空字符串时,没有匹配的文件名中。ksh93
有自己的高级模式匹配机制,可以达到相同的效果~(N)*.txt
shopt -s nullglob
将为不匹配的模式生成空字符串,而shopt -u nullglob
(标准设置)将生成模式本身。