我几乎可以肯定,这不是 shellzsh
提供的一种方法,但我想无论如何我都会问一下,以确保我没有遗漏手册中的任何内容。
使用zsh
shell,我可以从具有以下模式的目录中挑选出两个最大的可见文件
*(.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]))'])
可以$reply
在e
xpression 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 分隔的(带引号的)代码中,也是有效的[...]
。它不适用于其他分隔符,例如:...:
或 {...}
。