Search code examples
bashmacosunixsh

Why doesn't echo -n work in shell on Mac?


The man page for echo says:

 -n    Do not print the trailing newline character.  This may also be
       achieved by appending `\c' to the end of the string, as is done by
       iBCS2 compatible systems.  Note that this option as well as the
       effect of `\c' are implementation-defined in IEEE Std 1003.1-2001
       (``POSIX.1'') as amended by Cor. 1-2002.  Applications aiming for
       maximum portability are strongly encouraged to use printf(1) to
       suppress the newline character.

However this doesn't seem to work in sh on Mac:

sh-3.2$ echo $0
/bin/sh
sh-3.2$ which echo
/bin/echo
sh-3.2$ echo -n foo
-n foo

It works properly in bash:

bash-3.2$ echo $0
bash
bash-3.2$ which echo
/bin/echo
bash-3.2$ echo -n foo
foobash-3.2

FWIW this only seems to happen on Mac, on Linux it works properly:

$ echo $0
sh
$ echo -n foo
foo$

Solution

  • -n is a bash extension to echo. In version 3.2 (which ships with macOS), bash does not support the extension when invoked as sh. Starting with version 4.0 (some version of which is likely on your Linux box), bash does honor -n when invoked as sh.

    Update: the xpg_echo option determines if bash's built-in echo is POSIX-compliant or not. In bash 3.2 (or at least the macOS build of 3.2), this option defaults to on; in bash 4.x, it defaults to off.

    % sh -c 'shopt xpg_echo'
    xpg_echo        on
    % ./sh -c 'shopt xpg_echo'
    xpg_echo        off
    

    (./sh is a symlink to /usr/local/bin/bash, a local installation of bash 4.4 on my machine.)