2

如何在使用glob限定符搜索时排除一个或多个文件名后缀?

工作正常,这里我们匹配文件名后缀,而不是排除它们:

打印-rC1**/*。(文本)(.)
打印-rC1**/*。(jpg|png)(.)

我们并没有试图排除他们,这是行不通的:

打印-rC1**/*。(^txt)(.)
打印-rC1**/*。(^jpg|^png)(.)

zsh 5.9(x86_64-apple-darwin23.0)

2
  • 您是否启用了EXTENDED_GLOB(扩展_全局)外壳选项?的输出是什么setopt(设置选项)
    – 库萨拉南达
    5月18日9:20
  • @库萨拉南达combingchars交互式登录监视器shinstdin-zle(每行)
    – jsx97型
    5月18日9:24

2个答案2

重置为默认值
4

使用^x个模式需要扩展的地球仪要在中设置的shell选项兹什外壳:

setopt扩展_GLOB

之后,您应该能够查找任何文件名后缀既不是也不是的常规非隐藏文件.foo文件也不是.巴使用模式

./**/^*.(foo|bar)(.)

请注意*.(^foo|^bar)非常不同^*.(foo|bar).前者是指“任何包含.然后是不是foo公司或其他不一样的东西酒吧"(基本上全部的至少有一个点的文件,因为没有任何东西可以同时存在foo公司酒吧同时),而后者意味着“没有文件名.foo文件.巴在最后”.

如果您不包括./前缀,注意不要忘记---选项分隔打印否则,它将成为任意命令执行漏洞。

因此,在您的案例中:

打印-rC1--**/^*。(jpg|png)(.)
1

全球预选赛实际上并不是问题所在。事实上,它们使一些示例起作用。这里有三个独立的问题:如何解析glob限定符、glob运算符的语法以及控制这些限定符的选项。

$zsh-f#使用默认选项开始暗星%lsfoo.bar foo.jpg foo.png foo.txt暗星%echo*。(文本)(.)食品.txt暗星%echo*。(jpg|png)(.)foo.jpg foo.png文件

括号总是被接受用于在glob中进行分组,尽管在某些情况下,在它们成为glob的一部分之前,它们被解析为其他内容(算术表达式、glob限定符(稍后我将详细介绍)、函数定义等)。*.(文本)(.),最后一个带括号的块(.)被解析为glob限定符、和(文本)是只匹配精确文本的模式文本.

模式*.(jpg|png)(.)使用全局运算符 |意思是“或”。该部分(jpg|png)匹配两者jpg格式png公司.

暗星%回波*。(^txt)(.)zsh:未找到匹配项:*。(^txt)(.)暗星%setopt extended_glob暗星%echo*。(^txt)(.)foo.bar foo.jpg foo.png

默认情况下,^文本只匹配自身。这个全局运算符 ^仅当选项扩展的全局已设置。此选项始终在完成功能和zmv公司,但默认情况下处于禁用状态。默认情况下,它关闭的唯一原因是为了实现严格的向后兼容性(它最初并不存在,但已经存在了30多年)。很少有实际情况会产生影响(主要是如果你想通过#,^~在命令参数中没有引用它),即使它引用了,反斜杠或任何其他引号也会修复此问题。我建议把setopt扩展glob在您的.zshrc公司。启用此选项后,^文本匹配除之外的任何内容文本.

暗星%setopt extended_glob暗星%echo*。(^jpg|^png)(.)foo.bar foo.jpg foo.png foo.txt暗星%echo*^(jpg|png)(.)foo.bar foo.jpg foo.png foo.txt

模式(^jpg|^png)匹配任何不匹配的jpg格式或者那不是png公司。任何字符串都不是-jpg或not-png,所以(^jpg|^png)匹配所有内容。匹配两者都不是的任何内容jpg格式也不是png公司,使用^(jpg|png)如果你想否定的部分后面有更多的内容,你需要两个后面的括号,例如。*.(^(jpg|png)).gz匹配foo.bar.gz公司食品.txt.gz但不是foo.jpg.gz格式foo.png.gz公司.

现在让我们回到如何glob限定符已分析。默认情况下,末尾带括号的组被解析为全局限定符,除非它包含|或嵌套括号或~(当扩展的全局已启用)。

暗星%echo*.txt文件夹.txt暗星%echo*。(文本)zsh:未找到匹配项:*。(文本)暗星%echo*。((txt))食品.txt暗星%echo*。(文本)(.)文件夹.txt暗星%echo*。(png|jpg)foo.jpg foo.png文件

*.(文本),(文本)被解析为glob限定符(因此*.(文本)匹配名称以点结尾、可执行且设置了粘性位的文件)。使用双括号可以避免glob限定符解析。*.(png|jpg)未解释为使用glob限定符,因为|.*.(txt)(.)已经有了(.)解释为glob限定符,因此(文本)部分不能是glob限定符。

您可以通过取消设置来禁用glob限定符分析裸全球质量。我不建议这样做,因为不明确的模式很少见,并且当您确实需要glob限定符时,它需要额外的类型。请注意

暗星%setopt no_bare_glob_qual暗星%setopt no_extended_glob暗星%echo*。(文本)食品.txt暗星%echo*。(文本)(.)zsh:未找到匹配项:*。(文本)(.)暗星%echo*.txt(#q)zsh:未找到匹配项:*.txt(#q)暗星%setopt extended_glob暗星%echo*.txt(#q)foo.txt文件
  • 与@Kusalananda最初的回答相同,*.(^(jpg|png)).gz上的匹配项foo.bar.jpg.gz因为工具栏.jpg两者都不是jpg格式也不是png公司.你需要(^*.(jpg|png)).gz.IIRC有一些问答涵盖了常见的问题(或者可能针对ksh的问题)!(...)等效)。 5月18日9:56
  • @StéphaneChazelas是的,regexps中否定的技巧是我不想涉足的另一个问题。这个答案已经很长了。 5月18日10:02
  • 仍在展示*.(^(jpg|png)).gz是误导性的,因为它表明这是压缩文件的模式,而不是.jpg格式.png码不是这样的。 5月18日10:22

你必须登录来回答这个问题。

不是你想要的答案吗?浏览标记的其他问题.