3

Using ubuntu 10.10 I have the following that I run on the command-line:

result="$(ls -d !(*.*))"
chmod +x $result

This gets a list of files that have no extensions and makes them executable.

But when I move it to a script file (shell) it does not work. From what I have read around the forum this is something to do with command substitution being run in a different a subshell.

But I could not find a solution yet that works in my scrpt :(

So how do you get the result of a command and store it in a variable within a script?

code_fodder
  • 15,263
  • 17
  • 90
  • 167
  • You probably have `extglob` enabled on the interactive shell, but not in the script. Try adding `shopt -s extglob` before your command in the script. – user000001 Sep 08 '15 at 08:15
  • @user000001 yeah, you are right : ) ... ok I have to now go and research what extglob and shopt do. If you want to stick that into an answer I will mark it up appropriately. Thanks – code_fodder Sep 08 '15 at 08:21
  • I tried it like this: `bash -c 'shopt -s extglob; ls -d !(*.*)'` but no success. – Alfe Sep 08 '15 at 08:44
  • Whoa. `bash -c $'shopt -s extglob\nls -d !(*.*)'` works. This is weird as hell. Seems that the line is first parsed completely and then executed part by part. – Alfe Sep 08 '15 at 08:48
  • @Alfe haha, its a nice line of code, for me its easier to read over two lines :o ... else my brain hurts! – code_fodder Sep 08 '15 at 09:42

1 Answers1

3

(Since @user000001 does not seem to write their comment into an answer, I'll do the toiling of writing the answer. So credit should got to them, though.)

The feature you are using is the extglob (extended globbing) feature of the bash. This is per default enabled for interactive shells, and per default disabled for non-interactive shells (i. e. shell scripts). To enable it, use the command shopt -s extglob.

Note that this command only has effect for lines below it:

shopt -s extglob
ls -d !(*.*)

It does not effect parsing of the same line:

shopt -s extglob; ls -d !(*.*)   # won't work!!

In general I want to warn about using such special features of the bash. It makes the code rather unportable. I'd propose to use POSIX features and tools instead which enable porting the code to another platform rather easily, and they also represent a certain subset of possibilities more developers understand without having to consult the documentation first.

What you want to achieve could also be done using find. This also has the advantage of being unproblematic in combination with strange file names (e. g. containing spaces, quotes, etc.):

find . -maxdepth 1 -type f -name '*.*' -o -exec chmod +x "{}" \;
Alfe
  • 56,346
  • 20
  • 107
  • 159