Confusion about Newline Interpretation in Command Line Echo with Double Quotes

I've been learning about command line expansions and substitution, including path name expansion and command substitution. In my studies, I came across the concept of controlling these expansions using double quotes. While experimenting with these concepts, I encountered a behavior that I'm having trouble interpreting.

When I use the command echo $(cal), the output seems to ignore the newlines and is displayed as a single line:

August 2023 Su Mo Tu We Th Fr Sa 1 2 3 4 ...

However, when I use double quotes like this: echo "$(cal)", the output is correctly formatted with newlines:

    August 2023
Su Mo Tu We Th Fr Sa
      1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

From my understanding, using double quotes appears to render the newline characters (\n) correctly in the echo "$(cal)" command.

However, what confuses me is that when I try a similar approach with other characters, such as A\nB, using the command echo "A\nB", the output does not interpret the newline character and instead displays it as literal text:


I discovered that I need to use the -e switch, like this: echo -e "A\nB", to achieve the expected behavior:


Could someone please explain why the behavior differs between these two cases? Why does echo "$(cal)" correctly interpret newline characters within double quotes, while echo "A\nB" requires the -e switch for the correct interpretation?

I appreciate any insights or clarifications you can provide. Thank you!


  • There are no newline characters in "A\nB". C-style escape sequences aren't interpreted inside single quotes or double quotes. Backslash can be used in double-quoted strings to escape special characters like $ so they're treated literally, but \n has no special meaning and is interpreted literally.

    To make a string using C-style escape sequences, use $'string'.

    echo $'A\nB'

    will print


    The -e option to echo tells the echo command to interpret escape sequences inside the string when it's printing.