bash 命令顺序?

bash order of commands?

在想知道如何将 ls 传输到 cat 以输出一堆文件后,我意识到更好的方法是 cat $ $(ls *.py),但也意识到 $(ls *.py) cat $ 不起作用:

$(ls *.py) cat $                                                   1 ⨯
bash: command not found: 1.py

对我来说这很奇怪,为什么会这样?

第一:不要用$(ls *.py),直接用*.py。添加 $(ls) 没有任何用处,但它确实增加了几层处理和潜在的混淆。有关详细信息,请参阅 this question,但我会在接近结尾处给出一个快速摘要。

其次:当您使用 $(ls *.py)*.py 作为命令的一部分时,shell 会在执行命令之前“扩展”它。对于 *.py,这意味着用当前目录中匹配 *.py 的文件名替换它。因此,如果您使用 cat *.py,它将扩展为类似:

cat 1.py 2.py file.py otherfile.py

...这就是您想要的。但是 *.py cat 扩展为:

1.py 2.py file.py otherfile.py cat

...尝试执行 1.py 作为命令名称(它不作为命令存在,因此您会收到“找不到命令”错误),以及其他文件名和“cat " 作为参数。

使用 $(ls *.py) cat,它首先通过扩展 *.py 和 运行 ls 1.py 2.py file.py otherfile.py,捕获那个输出 ("1.py 2.py file.py otherfile.py"),将其拆分为“单词”(可能正确地将其拆分为文件名...除非任何文件有空格或您更改了IFS) 然后尝试扩展任何看起来像通配符的那些(就像它最初做的 *.py),然后最终从那些 + cat 构建一个命令。就像以前一样,结果是:

1.py 2.py file.py otherfile.py cat

如您所见,失败了。