Bash:使用文件名作为通配符的命令

时间:2016-07-14 19:01:22

标签: linux bash shell terminal wildcard

我之前在我的终端玩弄,发现我可以执行单字命令(' 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

任何人都知道这是为什么?

1 个答案:

答案 0 :(得分:2)

在bash解释并对结果执行操作之前,每个命令bash进程都会受到多种扩展的影响。最后一个是路径名扩展,其中bash检查包含任何未加引号的特殊字符*?和{的任何包含命令的单词(由先前的扩展和单词拆分产生) {1}},并将这些单词解释为表示文件名的模式。执行所有扩展后,将执行扩展命令中的任何重定向和变量赋值,并从命令中删除。如果仍有任何单词,则将第一个单词作为要运行的命令的名称。这个词的出处并不重要。

在路径名扩展中,[匹配任何字符串,包括空字符串。当bash对仅由*组成的单词执行路径名扩展时,它会扩展为工作目录中所有文件的名称,但以点(*)开头的文件除外。

因此,如果您的工作目录只包含一个名为.的文件,并执行命令ls,则bash会将该命令扩展为*并执行它,从而生成输出{ {1}}。同样,如果目录的内容是lslsecho,那么当您执行命令Hello,时,bash将其扩展为等效{{1} },命令输出World!

这不会像您认为的那样会对包含空格的文件名起作用,因为与模式匹配的每个文件名都会扩展为单个单词。这些不会随后拆分。 (Bash会在扩展过程中执行“分词”,但在路径名扩展之前会发生。)这通常是您想要的,否则*之类的命令将无法可靠地执行做你期望的事。

这不适用于别名,因为echo Hello, 'World!'读取命令时扩展别名,而不是在执行它们时扩展别名。这有几个含义,但其中之一是在执行任何扩展之前解释别名。另一个原因是别名的替换文本受到所有正常扩展的影响。