【问题标题】:Bash - delayed evaluation of wildcard fie execution: how does it workBash - 通配符执行的延迟评估:它是如何工作的
【发布时间】:2018-11-18 14:24:45
【问题描述】:

我一直试图理解为什么 Bash 会以我想要的方式解析以下内容,而不是我通过阅读 Bash 参考手册 (https://www.gnu.org/software/bash/manual/) 所期望的方式。从该手册中,我了解到通配符(例如第一行包含)在执行命令之前通过文件名扩展进行处理。但是,第二个 for 循环包含另一个通配符。如果在命令行处理时对其进行评估,它将与子目录中的文件不匹配。但这正是它的行为方式。直到运行时,在 cd 命令完成后,才会评估第二个通配符。 Bash 是如何做到这一点的?我想这是对命令行的非常纠结的评估。

for d in *;do
  cd "$d"
  for f in *.zip; do
    7z x "$f"
  done
  cd ..
done

【问题讨论】:

  • 通配符扩展对 bash 执行的每个(子)命令分别进行。
  • 这还不清楚。扩展发生在执行之前的命令评估期间。那么,您是说子命令是外部 for 循环中的所有内容吗? *.zip 扩展必须在外部 for 循环的每次迭代中以及 cd 命令完成后进行。这似乎与手册不一致。
  • @KevinBuchs 对于简单命令而不是复合命令是正确的,请参阅 3.2 Shell 命令,请注意,其他 posix shell 也是如此pubs.opengroup.org/onlinepubs/009695399/utilities/…

标签: bash shell


【解决方案1】:

从 cmets 更新

3.5 中描述的扩展是针对简单命令的,对于复合命令,第 3.2 章 Shell 命令描述了它们如何变成简单命令

3.2.3 列表是一个或多个管道的序列,由运算符“;”、“&”、“&&”或“||”之一分隔,并可选择以“;”、“&”或换行符。

[...]

用“;”分隔的命令按顺序执行; shell 等待每个命令依次终止。

原来的答案是

来自 bash 手册的不同部分

for 命令的语法是:

for name [ [in [words …] ] ; ] 执行命令;完成

扩展单词,并对结果列表中的每个成员执行一次命令,名称绑定到当前成员。 [...]

关于“词”的扩展

3.5 外壳扩展

在分割成令牌后在命令行上执行扩展。执行的扩展有七种:

  • 大括号扩展
  • 波浪扩展
  • 参数和变量扩展
  • 命令替换
  • 算术展开
  • 分词
  • 文件名扩展

更特别是* 用于文件名扩展(分词后的最后一个,因此没有分割包含空格的文件名的风险)

3.5.8.1 模式匹配

*

匹配任何字符串,包括空字符串。

关于您的命令请注意,在第一个循环中,如果文件不是目录,它将尝试 cd 导致错误,并且 cd .. 将被执行,因为没有错误检查

可以改进

for d in *;do
    [[ -d $d ]] || continue   # to skip files that are not a directory
    cd "$d" || continue       # to skip directory if `cd` fails
    for f in *.zip; do
        7z x "$f"
    done
    cd ..
done

【讨论】:

  • 您可以避免使用for d in */; do 对目录进行测试。
  • 我知道该脚本的要求,不需要测试非目录。然而,最后你没有回答我的问题。你没有解决我提出的具体问题。
  • 好吧,我对这个问题的理解更好,第二个 for 命令在第一个循环的每个循环中都被评估(单词被扩展),你也可以考虑x=hello; echo "$x",当时没有设置变量命令序列被解析,但扩展发生在调用 echo 之前
  • 最后,涵盖这一点的章节是 3.2,更准确地说是 3.2.3 和 3.2.4
  • 我认为手册中缺少的信息应该插入到第3.1.1节中,其中列出了处理步骤。第 3 步:将标记解析为简单和复合命令。第 4 步:执行各种 shell 扩展。他们不应该将这些列为线性步骤。步骤 3+ 应该说对于每个命令(简单命令或复合命令的元素)执行以下步骤,一次一个。那么步骤 4-7 应该嵌套在步骤 3+ 下,如 3+a、3+b、3+c、3+d。
猜你喜欢
  • 1970-01-01
  • 2021-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-03
  • 1970-01-01
  • 1970-01-01
  • 2020-09-15
相关资源
最近更新 更多