Bash – echo \\* – bash backslash escape behavior, is it evaluated backwards

bashechoescape-charactersquotingshell

So in bash,
When I do

echo \*
*

This seems right, as * is escaped and taken literally.

But I can't understand that,
when I do

echo \\*
\*

I thought the first backslash escaped the second one thus two backslash "\\" will give me one "\" in literal. and * followed carrying its special meaning.
I was expecting:

echo \\*
\file1 file2 file3

ANSWER SUMMARY:
Since \ is taken literally, echo \* will behave just as echo a*, which will find any file that starts with literal "a".

Follow up question,
If I want to print out exactly like

\file1 file2 file3

What command should I use?
e.g. like the following but I want no space

echo \\ * 
\ file1 file2 file3

Best Answer

If you don't have a file in the current directory whose name starts with a backslash, this is expected behaviour. Bash expands * to match any existing file names, but:

If the pattern does not match any existing filenames or pathnames, the pattern string shall be left unchanged.

Because there was no filename starting with \, the pattern was left as-is and echo is given the argument \*. This behaviour is often confusing, and some other shells, such as zsh, do not have it. You can change it in Bash using shopt -o failglob, which will then give an error as zsh does and help you diagnose the problem instead of misbehaving.

The * and ? pattern characters can appear anywhere in the word, and characters before and after are matched literally. That is why echo \\* and echo \\ * give such different output: the first matches anything that starts with \ (and fails) and the second outputs a \, and then all filenames.


The most straightforward way of getting the output you want safely is probably to use printf:

printf '\\'; printf "%s " *

echo * is unsafe in the case of unusual filenames with - or \ in them in any case.