37

If I have the file input.txt containing:

hello
world
!

Then executing the bash command echo $(cat input.txt) will output this:

hello world !

Why and how can I fix it to output exactly what is in the file how it is in the file?

muru
  • 197,895
  • 55
  • 485
  • 740

3 Answers3

47

If you use

echo "$(cat input.txt)"

it will work correctly.

Probably the input of echo is separated by newlines, and it will handle it as separate commands, so the result will be without newlines.

arian
  • 1,158
  • Nice! So what's the difference (if any) between $( ) and backticks? (Sorry if this is too tangential) – Chan-Ho Suh Apr 14 '12 at 02:49
  • They are equivalent, except for the fact that $(...) is easier to nest. In both cases, if you don't quote the result it will be tokenised into multiple arguments on white space. – James Henstridge Apr 14 '12 at 02:56
  • 3
    But the final newline character is omitted, even in double quotes. In contrast, Perl's backtick operator expands to the entire output of the command, including all newlines. – Keith Thompson Apr 14 '12 at 08:22
  • 6
    @KeithThompson yes, command substitution removes all trailing newlines from the output. That has the advantage of e.g. echo "$(date) something" stripping away the trailing newline from date's output, making that echo output the date and "something" on the same line. If you need to store a file or command output "as is", use mapfile (help mapfile), read -rd '' or a while read-loop. – geirha Apr 14 '12 at 08:26
  • Thanks everyone :-) I learned something from every comment here! – Chan-Ho Suh Apr 16 '12 at 07:13
9

Quoted from bash manual page, section Command Substitution:

Embedded newlines are not deleted, but they may be removed during word splitting.

A little further, same section :

If the substitution appears within double quotes, word splitting and pathname expansion are not performed on the results.

That's why echo "$(cat /etc/passwd)" works.

Additionally, one should be aware, that command substitution by POSIX specifications removes trailing newlines:

$ echo "$(printf "one\ntwo\n\n\n")"
one
two

Thus, outputting a file via $(cat file.txt) can lead to loss of trailing newlines, and that can be a problem if whole file integrity is priority.

Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
7

You can preserve newlines, for example by setting IFS to empty:

$ IFS=
$ a=$(cat links.txt)
$ echo "$a"
link1
link2
link3