Yes, echo $foo
will cause unexpected side-effects.
Issues with pathname expansion
Consider a directory with these four files:
$ ls
f* factor fo? foo
Now, observe that echo $foo
produces a list of eight file names:
$ foo=$(ls -1)
$ echo $foo
f* factor fo? foo factor fo? foo foo
This is because the unquoted $foo
in echo $foo
is subjected not just to word splitting (which is what eliminates the newlines) but also to pathname expansion.
If we use pattern substitution inside double quotes, however, we get the correct file list:
$ echo "${foo//$'\n'/ }"
f* factor fo? foo
Issues with bash's echo
As @lurker pointed out, echo
can act in surprising ways.
Consider a directory with three files:
$ ls
-e \none \text
Now, try:
$ foo=$(ls -1)
$ echo $foo
one ext
As you can see, the file names were mangled. This is because echo
interpreted the file name -e
not as a file name but as an option, the one that turns on interpretation of escape sequences. Thus, the file name whose characters are backslash-n-o-n-e becomes newline-one. and the file name whose characters are backslash-t-e-x-t becomes tab-ext.
Bash's echo command is not compatible with POSIX's echo
for which -e
is treated as text to be printed. Thus code relying on echo
is not portable. For this reason, among others, it is often recommended that new code use printf
rather than echo
.