echo and backslash-escaped caracters / new lines: how to write portable scripts ?

Posted on Tue 04 April 2017 in blog

While writing shell scripts you are using a lot of echo but did you think about portability of this simple statement? Can you say what will be diplayed, without testing, on your shell, the following tests:

echo \n \c '\n' '\c' "\n" "\c"
echo -e \n \c '\n' '\c' "\n" "\c"

? I can't, cause I know that the echo behavior is very implementation dependent, typically in dash, echo -e foo actually print -e foo because the dash's echo don't parses any options... Here is the bug I found on one of my shell scripts, simplified to this 9 bytes shell script:

$ cat /tmp/test.sh
#!/bin/sh
echo "$*"
$ /tmp/test.sh '1\n2'
1
2

I'm running Debian Squeeze so my sh is a dash, and the '\n' is interpreted by the dash's echo ... but I don't want it! The only portable workaround I found is:

$ cat /tmp/test.sh
#!/bin/sh
printf "%s\n" "$*"
$ /tmp/test.sh '1\n2'
1\n2

Conclusion: Keep a look at your input, if you don't want backslash-escaped chars to be interpreted and want to be portable, use printf! You can keep using echo when you have a full control on the input, so the sh Hello World will forever stay:

echo "Hello world"