bash variable visibility in subshell of command substitution

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.


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).

Tags:

Shell

Bash