为什么 chmod -R +x *.sh 不起作用?

Why doesn't chmod -R +x *.sh work?

因此,"chmod -R +x *.sh" 在 bash 中不起作用。可以找到替代方案 here。我的问题是:为什么它不起作用? chmod 缺少此功能是因为没有人费心去实现它,还是对此有更深层次的 bash/gnulib 哲学?

* 未被 chmod 处理;这是一个 shell 功能,称为 globbing。 shell 将 *.sh 扩展为当前目录中以 .sh 结尾的所有名称的列表,并将它们作为单独的参数传递给 chmod。 shell 不知道该命令有任何递归目录搜索方面,并且 chmod 永远不知道命令行中有 *

当你运行命令时,它首先被你的shell预处理然后执行。在预处理阶段,星号 * 被扩展为匹配项(在本例中为当前目录中的 shell 文件)。然后,-R 被忽略,因为没有可以递归的输入目录。

chmod不缺这个功能。它甚至没有得到您原来在命令中有星号的信息。

这是因为在 bash 中,通配符模式是由 shell 而不是程序扩展的。这与 Windows 不同,后者将模式传递给程序本身。让我们考虑这个样本目录结构:

curdir
|_ 1.sh
|_ 2.sh
|_ subdir
   |_ 3.sh
   |_ 4.sh

假设您要从 curdir 目录中 运行 命令 chmod -R +x *.sh。 shell 看到 *.sh 是通配符模式并将其扩展为 1.sh 2.sh 因为这些是与该模式匹配的文件名。最后执行的命令变为chmod -R +x 1.sh 2.sh。如您所见,参数的 none 是一个目录,因此 -R 开关无效。

有 shell 支持更复杂的模式。例如,如果您使用 zsh,则可以 运行 以下命令:

chmod +x **/*.sh # Note that -R is not required

zsh understands ** 模式表示递归搜索子目录。因此,这种情况下的最终命令将是:

chmod +x 1.sh 2.sh subdir/3.sh subdir/4.sh