Echoing/printing a bash `ls` command substitution without quotes
I have the following example:
$ echo $a
backups cache crash lib local lock log mail opt run snap spool tmp
$ echo "$a"
$ printf $a
$ printf "$a"
Why is the output so different? What do quotes do in this situation?
Could someone explain what’s going on here?
P.S. Found some explanation on the
Output from ls has newlines but displays on a single line. Why?
The newline characters can be checked this way:
ls | od -c
echo $a is the same as
echo backups cache crash lib local lock log mail opt run snap spool tmp
echo "$a" is the same as
The first argument for
printf is a formatting string and
printf $a is the same as
printf backups cache crash lib local lock log mail opt run snap spool tmp so it’s using the string
backups as the format and discarding the rest since there’s nothing like
%s in the formatting string to use them in. Just like:
$ printf foo whatever
$ printf '%sn' foo whatever
a="$(ls)" to try to create a scalar variable holding file names btw as that’s fragile, do
a=(*) to hold them in an array instead.
Thanks to @Ed Morton and @Kusalananda for the explanation.
I guess my problem was that I always thought that, by default,
ls splits the files using spaces or tabs. But in fact, it turned out that it separates them with new line characters but outputs the files in columns (sorted vertically) when printing to a terminal. Newline characters can be checked with:
ls | od -c
I’ll move the @Kusalananda’s answer from the comment section to an answer, since it was helpful:
echo outputs its arguments with spaces between them. This is what
echo $a, the shell splits the contents of
$a into several arguments based on spaces, tabs and newlines (and then also does filename globbing on each generated word).
echo then prints them with spaces between them.
echo "$a", you only ever give echo a single argument. The string
"$a" contains newlines from the output of
ls, and these are retained and outputted by