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

问题描述:

因此,“chmod -R + x * .sh”在bash中不起作用。替代品可以找到here。我的问题是:为什么它不起作用? chmod是不是缺乏这个功能,因为没有人打算实现它,或者是否存在一些更深的bash/gnulib哲学?为什么chmod -R + x * .sh不工作?

+1

我想你想要的是'find。 -name'* .sh'-exec chmod + x {} +' – ymonad

+0

使用'find'而不是'-exec' –

+1

为什么你认为它“不起作用”?它将名称以'.sh'结尾的所有文件和名称以'.sh'结尾的子目录中的所有文件设置为可执行位。工作得很好。 –

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

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。正如你所看到的,没有任何参数是一个目录,所以-R开关不起作用。

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

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

zshunderstands**模式指的是递归搜索子目录。因此,在这种情况下最终的命令将是:

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

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

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

chmod并不缺乏此功能。它甚至不会获得您的命令中最初带有星号的信息。