限制 z​​sh 中 glob 限定符的范围

限制 z​​sh 中 glob 限定符的范围

我几乎可以肯定,这不是 shellzsh提供的一种方法,但我想无论如何我都会问一下,以确保我没有遗漏手册中的任何内容。

使用zshshell,我可以从具有以下模式的目录中挑选出两个最大的可见文件

*(.OL[1,2])

如果我有一组目录,并且我想要每个目录中的两个最大文件,我相信我必须循环各个目录,然后使用

$dirpath/*(.OL[1,2])

(其中$dirpath是循环当前迭代中的目录路径)。

这将是好的能够说

*/*(.OL[1,2])

但是该 glob 限定符将应用于整个匹配名称列表,并且我会得到两个匹配项,而不是每个目录中的两个匹配项。

问题:是否可以将限定符的“范围”限制为仅影响最近的路径组件?

答案1

你不需要循环。一个中间变量就足够了。使用^参数扩展印记分布在数组上。

dirpath=(*(N-/))
print -rC1 -- $^dirpath/*(.NOL[1,2])

或者您可以使用匿名函数来避免临时变量(它成为$argv/$@匿名函数参数):

() {print -rC1 -- $^@/*(.NOL[1,2])} *(N-/)

答案2

另一种方法可能是这样的:

print -rC1 -- *(N-/e['reply=($REPLY/*(N.OL[1,2]))'])

可以$replyexpression glob 限定符中设置数组以进一步返回文件列表。因此,在这里,我们将目录或符号链接列表全局化,并为每个目录返回 2 个最大的常规文件。

请注意,e限定符语法是e:code:,其中可以使用除:分隔符之外的其他字符,或者像e{code},这样的对e[code](也可以使用e(code)和 ,e<code>但是那些(, ), <,>也需要用引号引起来)。但请注意,单词扩展是在部分中执行的code,实际上是在 glob 限定符中的任何位置,这很好,因为您可以在其中使用变量,例如*(L+$min_size),但这里意味着您通常需要将code内部单引号放在防止的扩展。

现在,(和这是我最近学到的一个技巧:) 如果您使用恰好是通配符(包括?*但也包括[,对)的字符代替 ,]作为分隔符并将分隔符保留在引号之外,那么您无需担心该字符是否会出现在代码,因为不带引号的*分隔符只能与另一个不带引号的分隔符匹配*,对于[vs也是如此]

因此*(N-/e['reply=($REPLY/*(N.OL[1,2]))']),即使]碰巧发生在由 unquoted 分隔的(带引号的)代码中,也是有效的[...]。它不适用于其他分隔符,例如:...:{...}

相关内容