我之前在我的终端玩弄,发现我可以执行单字命令(' ls'' cat',' python2.7', '退出')通过创建一个与命令相同的文件或目录。但是,我无法执行多字词'命令(' rm \ -rf *',' ls -a',' python2.7 \ test.py')(这也让我发现了您无法删除名为' -rf'和rm -rf *')的目录,除非参数按字母顺序排列。看起来,当你只是传入*到bash时,它按字母顺序读取文件/目录的名称,将每个连续的名称作为参数传递给上一个命令。例如:
$ mkdir cat
$ touch dog
$ vim dog # at this point I put 'Hello!' into dog
$ *
Hello!
为什么通配符不允许我执行包含空格的文件命令,但允许我执行多个文件名的命令?谢谢!
编辑:别名也因某些原因无法工作。例如:$ alias lsa='ls -a'
$ mkdir lsa
$ *
No command 'lsa' found, did you mean:
...
lsa: command not found
任何人都知道这是为什么?
答案 0 :(得分:2)
在bash解释并对结果执行操作之前,每个命令bash进程都会受到多种扩展的影响。最后一个是路径名扩展,其中bash检查包含任何未加引号的特殊字符*
,?
和{的任何包含命令的单词(由先前的扩展和单词拆分产生) {1}},并将这些单词解释为表示文件名的模式。执行所有扩展后,将执行扩展命令中的任何重定向和变量赋值,并从命令中删除。如果仍有任何单词,则将第一个单词作为要运行的命令的名称。这个词的出处并不重要。
在路径名扩展中,[
匹配任何字符串,包括空字符串。当bash对仅由*
组成的单词执行路径名扩展时,它会扩展为工作目录中所有文件的名称,但以点(*
)开头的文件除外。
因此,如果您的工作目录只包含一个名为.
的文件,并执行命令ls
,则bash会将该命令扩展为*
并执行它,从而生成输出{ {1}}。同样,如果目录的内容是ls
,ls
和echo
,那么当您执行命令Hello,
时,bash将其扩展为等效{{1} },命令输出World!
。
这不会像您认为的那样会对包含空格的文件名起作用,因为与模式匹配的每个文件名都会扩展为单个单词。这些不会随后拆分。 (Bash会在扩展过程中执行“分词”,但在路径名扩展之前会发生。)这通常是您想要的,否则*
之类的命令将无法可靠地执行做你期望的事。
这不适用于别名,因为echo Hello, 'World!'
在读取命令时扩展别名,而不是在执行它们时扩展别名。这有几个含义,但其中之一是在执行任何扩展之前解释别名。另一个原因是别名的替换文本受到所有正常扩展的影响。