You are writing a script that will run on multiple versions of Unix and Linux and you need echo to behave consistently even if it is not running on bash.
Use printf "%b"
whatever
, or test for the system and set xpg_echo
using shopt
-s xpg_echo
as needed.
If you omit the "%b"
format
string (for example, printf
whatever
), then printf
will try to interpret any % characters in
whatever
, which is probably not what you
want. The "%b"
format is an addition
to the standard printf format that will prevent
that misinterpretation and also expand backslash escape sequences in
whatever
.
Setting xpg_echo
is less
consistent since it only works on
bash. It can be effective if you are sure that
you’ll only every run under bash, and not under
sh or another similar shell that doesn’t use
xpg_echo
.
Using printf requires changes to how you
write echo
statements, but it’s
defined by POSIX and should be consistent across any POSIX shell
anywhere. Specifically, you have to write printf "%b"
instead of just echo
.
If you automatically type $b
instead of %b
you will be unhappy
because that will print a blank line, since you have specified a null
format. That is unless $b
is
actually defined, in which case the results depend on the value of
$b
. Either way, this can be a very
difficult bug to find since $b
and
%b
look very similar:
$ printf "%b" "Works" Works $ printf "$b" "Broken" $
In some shells, built-in echo behaves differently than the external echo used on other systems. This is not always obvious when running on Linux since /bin/sh is actually bash (usually;it could also be dash on Ubuntu 6.10+), and there are similar circumstances on some BSDs. The difference is in how echo does or does not expand back-slash-escape sequences. Shell built-in versions tend not to expand, while external versions (e.g., /bin/echo and /usr/bin/echo) tend to expand;but again, that can change from system to system.
Typical Linux (/bin/bash):
$ type -a echo
echo is a shell builtin
echo is /bin/echo
$ builtin echo "one two
three"
one two
three
$ /bin/echo "one two
three"
one two
three
$ echo -e "one two
three"
one → two
three
$ /bin/echo -e "one two
three"
one → two
three
$ shopt -s xpg_echo
$ builtin echo "one two
three"
one → two
three
$ shopt -u xpg_echo
$ builtin echo "one two
three"
one two
three
Typical BSD (/bin/csh, then /bin/sh):
$ which echo
echo: shell built-in command.
$ echo "one two
three"
one two
three
$ /bin/echo "one two
three"
one two
three
$ echo -e "one two
three"
-e one two
three
$ /bin/echo -e "one two
three"
-e one two
three
$ printf "%b" "one two
three"
one → two
three$ /bin/sh
$ echo "one two
three"
one two
three
$ echo -e "one two
three"
one → two
three
$ printf "%b" "one two
three"
one → two
three
$ which echo /usr/bin/echo $ type echo echo is a shell builtin $ echo "one two three" one → two three $ echo -e "one two three" -e one → two three $ printf "%b" "one two three" one → two three
18.119.172.146