Velvet Star Monitor

Standout celebrity highlights with iconic style.

updates

Command substitution doesn't work when it's the input to `read`

Writer Matthew Barrera

If I run the following script of command substitution:

var=$(ls)
echo $var

it works as expected -- the output is the results of ls command. But if I assign the variable using read:

read var
echo $var

in which $(ls) is the input to read, the output is the literal

$(ls)

instead of the output of the ls command.

I don't understand why there is such a difference because I think the contents of variable var should be the same in both cases and therefore the shell should treat the echo command in both exactly the same way.

Could you please give an explanation?

3

2 Answers

Command substitution is a shell expansion, and Bash doesn't perform expansions on the input to read.

This is a good thing, because read is supposed to capture whatever nonsense (or brilliance) the naive (or expert) user typed.

Try entering any input that the shell would usually expand, and you will find the same thing happens...

$ var=~ # ~ was expanded before assignment
$ echo $var
/home/zanna
$ read -r var
~
$ echo $var
~

There are some sort-of exceptions to this - read treats backslash characters as escapes

The backslash character ‘\’ may be used to remove any special meaning for the next character read and for line continuation.

This is almost never what you actually want (you want read to capture whatever the user typed including any backslashes), so you should habitually use the -r flag with read (like I have done in my examples):

-r

If this option is given, backslash does not act as an escape character. The backslash is considered to be part of the line. In particular, a backslash-newline pair may not be used as a line continuation.

The other exception is that the input is split into fields in a way similar to word-splitting, so you can assign to multiple variables:

$ read -r var
one two three
$ echo $var
one two three
$ read -r baa ram ewe
one two three
$ echo $ram
two

Quotes are from this section of the Bash manual - scroll down to find read, or run help read in the shell for a shorter version.

var=$(ls) executes command ls and assigns the output to a variable In the second case, it just assigns the string you entered to a variable, there is no execution happening. It is just a string assigned to a variable, bash does not do anything with it.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

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