1

So, "chmod -R +x *.sh" does not work in bash. Alternatives can be found here. My question is: why doesn't it work? Does chmod simply lack this feature because nobody bothered to implement it or is there some deeper bash/gnulib philosophy to this?

Community
  • 1
  • 1
dijxtra
  • 2,681
  • 4
  • 25
  • 37

3 Answers3

3

The * isn't processed by chmod; it's a shell feature known as globbing. The shell expands *.sh to a list of all names in the current directory that end in .sh and passes them to chmod as separate arguments. The shell doesn't know that there's any recursive directory search aspect to the command, and chmod never knows the command line had a * in it.

user2357112
  • 260,549
  • 28
  • 431
  • 505
3

This is because in bash, the wildcard pattern is expanded by the shell and not by the program. This is unlike in Windows where the pattern is passed to the program itself. Let's consider this sample directoy structure:

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

Say you're running the command chmod -R +x *.sh from within the curdir directory. The shell sees that *.sh is a wildcard pattern and expands it to 1.sh 2.sh since those are the filenames that match the pattern. The final command that is executed becomes chmod -R +x 1.sh 2.sh. As you can see, none of the arguments is a directory, so the -R switch has no effect.

There are shells that have support for more complex patterns. For example, if you're using zsh, you can run the following command:

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

zsh understands the ** pattern to mean a recursive search into subdirectories. Thus, the final command in this case will be:

chmod +x 1.sh 2.sh subdir/3.sh subdir/4.sh
svsd
  • 1,831
  • 9
  • 14
1

When you run the command, it is first preprocessed by your shell and then executed. During preprocessing phase, the star symbol * gets expanded into matches (in this case shell files in current directory). Then, -R gets ignored, as there are no input directories that could be recursed.

chmod is not lacking this feature. It doesn't even get the information that you had originally star symbol in your command.

buff
  • 2,063
  • 10
  • 16