Bug in echo command in linux shell? [duplicate]

2019-08-18 00:01发布

问题:

This question already has an answer here:

  • bash shell gives weird result when directory exists vs not 2 answers

There is weird thing i noticed today

If i have file by name i or o or e

and echo any string with any of the above character within square bracet - [] then it always prints only the character

$ touch i e o

$ ls -lrh
total 0
-rw-r--r-- 1 root root 0 May 23 08:24 o
-rw-r--r-- 1 root root 0 May 23 08:24 i
-rw-r--r-- 1 root root 0 May 23 08:24 e


$ echo [offline]
e i o

$ echo [online]
e i o

$ echo [error]
e o

$ echo [soap]
o

and if i remove the file everything works fine

$ rm -f e i o

$ ls
$ echo [offline]
[offline]

$ echo [online]
[online]

$ echo [error]
[error]

$ echo [soap]
[soap]

So what is the relation between echo and these file names ?

回答1:

The shell performs pathname expansion on the command line arguments. Pathname expansion looks at each unquoted argument in turn and tries to replace it with a list of matching filenames. For this purpose the following wildcards apply:

  • * means 0 or more characters, any characters;

  • ? means 1 character, any character;

  • [<chars>] means 1 character, one of the given <chars>.

If one or more file names match, the command line argument is replaced with the list of matching file names. If no file names match, the command line argument is left as is.

So in your case:

  • [offline] is an unquoted command line argument, which

  • Includes the wildcard [...], and

  • The files e, i and o match the wildcard, so

  • The shell replaces the argument with the list of matching file names.

Morality: Always but always quote the arguments which you don't want the shell to expand. Always say echo '[offline]', never say echo [offline].



标签: shell echo