When you run this command:
ls
the terminal displays the output of ls
.
When you run this command:
echo $(ls)
the shell captures the output of $(ls)
and performs word splitting on it. With the default IFS
, this means that all sequences of white space, including newline characters, are replaced by a single blank. That is why the output of echo $(ls)
appears on one line.
For an advanced discussion of word splitting, see Greg's FAQ.
Suppressing word splitting
The shell does not perform word splitting on strings in quotes. Thus, you can suppress word splitting and retain the multiline output with:
echo "$(ls)"
ls
and multiline output
You may have noticed that ls
sometimes prints more than one file per line:
$ ls
file1 file2 file3 file4 file5 file6
This is the default when the output of ls
goes to a terminal. When the output is not going directly to a terminal, ls
changes its default to one file per line:
$ echo "$(ls)"
file1
file2
file3
file4
file5
file6
This behavior is documented in man ls
.
Another subtlety: command substitution and trailing newlines
$(...)
is command substitution and the shell removes trailing newline characters from output of command substitution. This normally is not noticeable because, by default, echo
adds one newline to the end of its output. So, if you lose one newline from the end of $(...)
and you gain one from echo
, there is no change. If, however, the output of your command ends with 2 or more newline characters while echo
adds back only one, your output will be missing one or more newlines. As an example, we can use printf
to generate trailing newline characters. Note that both of the following commands, despite the different number of newlines, produce the same output of one blank line:
$ echo "$(printf "\n")"
$ echo "$(printf "\n\n\n\n\n")"
$
This behavior is documented in man bash
.
Another surprise: pathname expansion, twice
Let's create three files:
$ touch 'file?' file1 file2
Observe the difference between ls file?
and echo $(ls file?)
:
$ ls file?
file? file1 file2
$ echo $(ls file?)
file? file1 file2 file1 file2
In the case of echo $(ls file?)
, the file glob file?
is expanded twice, causing the file names file1
and file2
to appear twice in the output. This is because, as Jeffiekins points out, pathname expansion is performed first by the shell before ls
is run and then again before echo
is run.
The second pathname expansion can be suppressed if we used double-quotes:
$ echo "$(ls file?)"
file?
file1
file2
ls
by itself doesn't give you multiple items per line? – Chris Davies May 17 '16 at 07:59echo *
? – jdh8 Oct 03 '16 at 08:18