This gets a bit complicated. There are actually three different cases: two POSIX variants, and what Bash does.
First, the shell handles what you wrote. The POSIX shell language, along with Bash, supports backslash quoting, which
preserves the literal value of the following character
So \\
represents a single \
in the argument given to the command.
Your example, echo \\\\\\
, has three pairs of backslashes. The shell interprets those escapes and gives three backslashes, \\\
, as the argument to echo
(equivalent to echo '\\\'
).
In all cases, the echo
command gets the same argument, but they interpret it differently.
POSIX
There is an optional POSIX extension (XSI, or X/Open System Interfaces), which is very commonly supported today. It's possible to be POSIX-conformant without supporting XSI, and it makes a difference in this situation.
With XSI, echo
requires that the backslash escapes are interpreted within arguments, including
\\
Write a <backslash> character.
Without XSI, POSIX instead states that
If the first operand is -n, or if any of the operands contain a <backslash> character, the results are implementation-defined.
and so no particular outcome is specified (or, both versions you saw are allowed).
POSIX/XSI echo
will interpret the first pair of backslashes as an escape itself, resulting in \\
as the output.
Bash
Bash's builtin echo
, on the other hand, does not interpret escape sequences unless you provide the -e
option to ask for it explicitly.
In Bash's POSIX mode, which is enabled in various circumstances (including when it is invoked as sh
), it still does the same thing (which is allowed as "implementation-defined" behaviour). If you enable the xpg_echo
option using shopt -s xpg_echo
, or your bash
executable was built with the --enable-xpg-echo-default
configuration option, you will get the POSIX/XSI behaviour.
GNU coreutils echo
does the same thing.
That means that:
- Under Bash, only the shell-level interpretation happens, and you get three backslashes outputted.
- Under a POSIX/XSI environment, the backslashes are interpreted twice, and you get two backslashes outputted.
- Under a pure POSIX environment, the implementation gets to choose a behaviour. Either version of the output you saw is allowed.
- You can configure Bash to have the XSI behaviour of interpreting escapes automatically with
shopt -s xpg_echo
, but it won't ever be enabled without explicitly asking for it.