Bash 扩展 Globbing
发布于 2008 年 10 月 8 日
bash 中的通配符被称为路径名扩展。路径名扩展有时也被称为 globbing。当您在命令中输入 "*"、"?" 和 "[...]" 语法时,路径名扩展会“扩展”它们,例如
$ ls *.jpg # List all JPEG files $ ls ?.jpg # List JPEG files with 1 char names (eg a.jpg, 1.jpg) $ rm [A-Z]*.jpg # Remove JPEG files that start with a capital letter关于路径名扩展的一个微妙但常常被忽略的点是,它是由 bash 完成的,而不是由操作系统或正在运行的程序完成的。程序永远看不到通配符,bash 在运行程序之前将扩展结果替换到命令行中。只有在编写代码并调用 exec() 及其朋友时,这一点才显得重要:如果您不通过 bash 执行程序,则传递给 exec() 的命令行中的任何通配符都不会被扩展。
但这些并非 bash 支持的唯一的通配符形式。其他形式被称为扩展 globbing,您必须先启用它们才能使用它们
$ shopt -s extglobbash 手册页中描述的扩展 globbing
?(pattern-list) Matches zero or one occurrence of the given patterns *(pattern-list) Matches zero or more occurrences of the given patterns +(pattern-list) Matches one or more occurrences of the given patterns @(pattern-list) Matches one of the given patterns !(pattern-list) Matches anything except one of the given patterns这里的模式列表是由竖线“|”(也称为管道符号)分隔的项目列表。如果你看一下这些,你就会明白为什么选择前导字符,因为它与正则表达式语法中使用的字符相匹配
Bash Regular Expression ?(pattern-list) (...|...)? *(pattern-list) (...|...)* +(pattern-list) (...|...)+ @(pattern-list) (...|...) [@ not a RE syntax] !(pattern-list) "!" used as for negative assertions in RE syntax好吧,除了“@”字符,你就能明白为什么了……
例如,要列出所有以“ab”或“def”开头的 JPEG 和 GIF 文件,您可以这样做
$ ls +(ab|def)*+(.jpg|.gif)当然,您也可以在不使用扩展 globbing 的情况下执行此操作
# ls ab*.jpg ab*.gif def*.jpg def*.gif
要列出所有与正则表达式“ab(2|3)+.jpg”匹配的文件,您可以这样做
$ ls ab+(2|3).jpg这是使用常规 globbing 无法实现的。注意:这匹配诸如 ab2.jpg、ab3.jpg、ab2222.jpg、ab333.jpg 等文件。
但是,可能最有趣的扩展 globbing 语法是“!(...)”语法,用于匹配除(即不匹配)以外的所有内容。但是,请注意,这并不总是按您期望的方式工作。例如,让我们列出所有不是 JPEG 或 GIF 的文件。人们首先想到的可能是这样的
$ ls *!(.jpg|.gif) # wrong, Wrong, WRONG但这不起作用,因为任何文件名的“.jpg”和“.gif”最终都会被“*”匹配,并且文件名末尾的空字符串最终会不匹配“!(...)”模式。正确的语法是
$ ls !(*.jpg|*.gif)
对于一个更复杂的否定示例,让我们回到第一个例子,列出所有不是 JPEG 或 GIF 文件并且以“ab”或“def”开头的文件。这实际上非常简单,我们只需将第一个示例嵌套在“!(...)”中
$ ls !(+(ab|def)*+(.jpg|.gif))当然,就像复杂的正则表达式一样,写完 10 分钟后,这将完全无法理解。