Bash 通配符作为非文件参数。示例: apt-get 删除 pkg-*

Bash 通配符作为非文件参数。示例: apt-get 删除 pkg-*

我知道*其他 glob 模式会根据当前工作目录通过路径名扩展转换为单词。然而,某些命令似乎将它们用于非文件参数。例如,我用来dpkg -l pkg-*列出带有pkg-.我认为程序在扩展之前无法看到它们的参数,只能在扩展之后看到。难道不是这样吗?这是如何运作的?

我最近读到了作者称之为的一些 bash 怪异现象魔法别名,我认为可以用来做到这一点。

答案1

问题是,如果与pkg-*当前目录中的任何文件都不匹配,则会按原样传递给 dpkg。这实际上是个坏主意。人们应该一直引用它。例如:dpkg -l pkg-\*

答案2

你是对的:程序只能看到它们被 shell 扩展后的参数,它们看不到原始的通配符。然而,Bourne shell 及其后继者(ksh、bash、dash 等)如果匹配 0 个文件,则不会展开通配符。因此只要pkg-当前目录中不存在名称以 开头的文件,就将和dpkg -l pkg*两个参数传递给.-lpkg-*dpkg

这样做是为了方便避免在不打算解释为文件名且不匹配任何文件名的单词中引用通配符。但有些 shell 的行为不同,如果通配符不匹配任何内容,则可以中止命令(csh、tcsh、zsh 和 Fish 中的默认行为 - 除非有多个连续模式,其中一些模式只要满足以下条件就可以不匹配任何内容)至少有一个与文件匹配)或展开通配符匹配( zsh 中的Nglob 修饰符或null_globshell 选项、Nksh 中的模式选项、nullglobbash 中的 shell 选项)。后一种行为具有规律性的优点(非匹配模式扩展到匹配列表,与匹配一个或多个文件的模式相同),这使得它在脚本中更受欢迎。

为了确保模式不会意外扩展,请引用其通配符:dpkg -l 'pkg-*'dpkg -l pkg-\*

常用的 shell 都不知道哪些命令的哪些参数是文件(需要通配符)以及哪些参数是其他最好不要处理的东西。 Zsh 可以通过在特定命令noglob之前写入来禁用该命令的通配符,例如noglob dpkg -l pkg-*noglob经常用于别名,例如alias lynx='noglob lynx'. Simon Tatham 描述的 bash“神奇别名”模拟了 zsh 的noglob.

相关内容