To complement Colwin's effective answer with why the double quotes are needed:
If you pass an unquoted command substitution (e.g, `ls -l` or, better, $(ls -l)) or variable reference (e.g., $var), the shell modifies the command output / variable value before passing the argument to the command.
This applies to all POSIX-compatible shells, not just bash.
Specifically, the following so-called shell expansions
are performed:
word-splitting: the output is split into (potentially) multiple words by whitespace, including newlines (by default; the split characters can be set via $IFS)
globbing (filename expansion): each resulting word is interpreted as a filename pattern and matched agains files in the current directory, and each matching filename becomes its own word, with all resulting words replacing the original word; by default, if nothing matches, the word is left as-is.
The resulting words are then passed as individual arguments to the target command.
By contrast, if you double-quote a command substitution ("$(ls -l)" or variable reference ("$var"), these expansions do NOT take place, and the output / value is passed as-is to the target command.
Therefore, in the case at hand:
- the shell removes all newlines from the output of
ls -l
- and then passes the resulting words individually, as multiple arguments to
echo
echo simply concatenates multiple arguments you pass to it with spaces, which is why you're seeing the single-line output printed in your question.
In short: Due to not double-quoting `ls -l`, echo `ls -l` prints a space-separated, single-line list of the words contained in the output from ls -l.