7

I am reading a Linux shell scripting book and have found the following warning:

"Command substitution creates what's called a subshell to run the enclosed command. A subshell is separate child shell generated from the shell that's running the script. Because of that, any variables you create in the script aren't available to the subshell command".

I have tried to create a variable in my current bash shell's CLI and then enter the subshell to check whether I can print it on the screen. So yes, I can't do it, seems to be according the citation above. However, I have run the following script with command substitution:

#!/bin/bash
var=5.5555
ans=$(echo $var)
echo $ans

And the result is:

5.5555

As I understood, it shouldn't print the value of var since the subshell shouldn't be able to "see it". Why does it happen?

  • But the comment in the book says it does. I even included $BASH_SUBSHELL variable to print out in the command substitution and it printed 1 which means it created a subshell. – Donatas Sep 12 '16 at 7:54
  • 3
    Your book isn't very good. – Michael Homer Sep 12 '16 at 8:32
  • 1
    At the very least that statement is unclear and misleading, and otherwise it's just outright wrong, as you've demonstrated in this question. – Michael Homer Sep 12 '16 at 8:40
  • 1
    Charitably I'd have to guess that the book means "are not available for assignment" (with the thinking that that means the "variable" is unavailable), but it's a very unhelpful way of saying so if that's really what they meant. – Michael Homer Sep 12 '16 at 8:41
  • 1
    Read some of our questions on sushell, such as unix.stackexchange.com/questions/157957/… and unix.stackexchange.com/questions/138463/… – Gilles Sep 12 '16 at 8:41
9

The statement:

Because of that, any variables you create in the script aren't available to the subshell command.

is false. The scope of a variable defined in the parent shell is the entire script (including subshells created with command substitution).

Running:

#!/bin/bash
var=5.5555
ans1=$(echo $var)
ans2=$(var=6; echo $var)
echo $ans1
echo $ans2

will give the result:

5.5555
6

$var is resolved by the subshell:

  • if no local variable is specified, the value of three global variable is used
  • if a local variable is specified, it uses its value

See also the example 21-2.

9

The statement as quoted is not true. It is also not true that the variable has been pre-substituted before the subshell runs.

You can validate this directly using variable indirection:

$ x=hello
$ echo Result is $(y=x ; echo ${!y} ; echo world)
Result is hello world

The variable x is definitely available directly to the subshell (rather than having had its value previously expanded) because ${!y} reads from the variable whose name is stored in y - which didn't exist at the time the subshell was created.


A charitable reading of the passage from the book would be that it means to say that the "variable" is unavailable because you can't modify its value persistently. Any variable assignments you make within a subshell are not available to the parent shell afterwards, whether that's making new variables (like y) or assigning replacement values to existing variables. If the subshell assigned to x, the new value would have effect inside the subshell, but reading from it afterwards would give the original value:

$ x=world
$ echo $(x=hello ; echo $x)
hello
$ echo $x
world

It's not a very clear way of expressing that, at least in the passage you've quoted. If the whole book is like that, you may be able to find a better one (or read questions here instead).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.