【问题标题】:Bash: Using filenames as commands with the wildcardBash:使用文件名作为带有通配符的命令
【发布时间】:2016-07-14 19:01:21
【问题描述】:

我早些时候在我的终端上玩耍,发现我可以通过创建一个与命令。但是,我不能执行 'multi-word' 命令('rm\ -rf *','ls -a', 'python2.7\ test.py')(这也让我发现你不能使用 'rm -rf *' 删除名为 '-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

有人知道这是为什么吗?

【问题讨论】:

  • 不知道这样做的目的是什么,只是不建议创建名为“sudo”的文件。
  • 我只是觉得它很简洁,想知道更多关于它背后的机制的细节。不知道为什么启用它。
  • 也许“strace *”会有助于理解...

标签: linux bash shell terminal wildcard


【解决方案1】:

在 bash 解释并作用于结果之前,bash 处理的每个命令都受到多种扩展的影响。最后一个是路径名扩展,其中 bash 检查命令的单词(由先前的扩展和分词产生)是否包含任何未引用的特殊字符 *、? 和 [,以及将这些词解释为表示文件名的模式。执行所有扩展后,将执行扩展命令中的任何重定向和变量分配并将其从命令中删除。如果还有任何单词,则将第一个单词作为要运行的命令的名称。这个词的出处并不重要。

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

因此,如果您的工作目录仅包含一个名为 ls 的文件,并且您执行命令 *,则 bash 将该命令扩展为 ls 并执行它,生成输出 ls。类似地,如果目录的内容是echo、Hello,和World!,那么当你执行命令*时,bash会将其扩展为等同于echo Hello, 'World!',命令输出Hello, World!。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-05
    • 1970-01-01
    • 1970-01-01
    • 2012-09-18
    • 2018-01-24
    相关资源
    最近更新 更多