这是一个 zsh 扩展的 glob 模式。重点是将目录层次结构下的所有文件与模式匹配,特定子层次结构除外。标题中的模式有效,但我想要一些不需要重复的东西long/path/
。
我尝试了以下方法:
long/path/(^(bad-1|bad-2)/|)**/^*.(complex|pattern)(.)
long/path/(**~(bad-1|bad-2)/*)/^*.(complex|pattern)(.)
添加KSH_GLOB
:
long/path/?(^(bad-1|bad-2)/)**/^*.(complex|pattern)(.)
它们都会导致错误模式错误。看来问题出/
在括号中。文件说:
如上所述,用作目录分隔符的“/”可能不会出现在括号内
这让我感到困惑,因为这(dir/)#
是一个很好的模式。它甚至在文档中提到:
`(foo/)#' 形式的路径名组件匹配由零个或多个匹配模式 foo 的目录组成的路径。
我想这是个例外。
明确地说,我正在寻找等价物。这不包括:
long/path/^(bad-1|bad-2)/**/^*.(complex|pattern)(.)
因为它排除了诸如long/path/good.pattern
, 和
long/path/(^(bad-1|bad-2)/)#/^*.(complex|pattern)(.)
long/path/**/^*.(complex|pattern)~*/(bad-1|bad-2)/*(.)
因为那些排除了诸如 what's under 之类的东西long/path/good/bad-1
。
编辑:只是提一下,解决方案不一定只需要使用通配符。如果可以通过添加大括号或历史扩展或其他一些 zsh 工具来完成,那就太好了。
编辑 2:按照我自己的想法,我尝试了历史扩展:
long/path/**/^*.(complex|pattern)~!{#$:s/\**//}/(bad-1|bad-2)/*(.)
然而,这失败了,因为 1) 当前行的最后一个字是扩展所在的那个之前的那个,以及 2) 因为历史替换似乎是在 glob 扩展之后完成的(我一定是误解了这里的某些东西,因为那似乎违背文档;也许所有扩展都是逐字逐句完成的)。
我也试过大括号扩展:
( IFS=\~; printf "%s\n" long/path/{**/^*.(complex|pattern),(bad-1|bad-2)/*(.)} )
它没有用。这 2 个 glob 模式仍然被视为单独的词,而不是被连接成一个单一的模式。我想IFS
这里没有考虑。说得通。
我还尝试在 glob 限定符中进行替换:
+/**/^*.(complex|pattern)~+/(bad-1|bad-2)/*(.:s,+,long/path,)
但是,当然,那是行不通的,因为替换是在匹配之后而不是之前进行的。
知道了!双斜杠标记前缀:
有时,在找到某项用途之前,您不会意识到它是一项功能。我无法相信连续的斜线相当于一个斜线的事实竟然如此有用。:)
(...)
列表的文档/
作为例外:否则可以通过使用表达式过滤结果来避免重复: