我正在尝试使用 find 返回在其路径中具有特定目录但在文件路径中的任何位置都没有另一个特定目录的所有文件名。就像是:
myRegex= <regex>
targetDir= <source directory>
find $targetDir -regex $myRegex -print
我知道我也可以通过将一个 find 命令传递到另一个命令来做到这一点,但我想知道如何使用单个正则表达式来做到这一点。
例如,我希望每个文件的路径中都有目录“好”,但无论组合如何,在其路径中的任何地方都没有目录“坏”。一些例子:
/good/file_I_want.txt #Captured
/good/bad/file_I_dont_want.txt #Not captured
/dir1/good/file_I_want.txt #Captured
/dir2/good/bad/file_I_dont_want.txt #Not captured
/dir1/good/dir2/file_I_want.txt #Captured
/dir1/good/dir2/bad/file_I_want.txt #Not captured
/bad/dir1/good/file_I_dont_want.txt #Not captured
请记住,某些文件名可能包含“好”或“坏”,但我只想说明目录名称。
/good/bad.txt #Captured
/bad/good.txt #Not captured
我的研究表明我应该使用 Negative Lookahead 和 Negative Lookbehind。但是,到目前为止,我尝试过的任何方法都没有奏效。一些帮助将不胜感激。谢谢。
正如 Inian 所说,您不需要
-regex
(这是非标准的,并且支持-regex
¹的实现之间的语法差异很大)。您可以使用
-path
它,但您也可以告诉find
不要输入名为 的目录bad
,这比发现其中的每个文件以便以后使用过滤掉它们更有效-path
:(
LC_ALL=C
sofind
的*
通配符不会阻塞字节序列在区域设置中不形成有效字符的文件名)。或者对于多个文件夹名称:
使用
zsh
,您还可以执行以下操作:或者对于数组中的列表:
不下降到称为,
bad
或(效率较低,如-path '*/good/*' ! -path '*/bad/*'
)的目录:In
zsh -o extendedglob
,~
是例外(和非)通配符运算符,而^
是否定运算符,并且#
是 0 或更多的前面的东西,如 regexp*
。${(~j[|])array}
将数组的元素与 连接起来|
,将|
其视为全局运算符而不是文字|
与~
.在
zsh
中,您可以在之后使用 PCRE 匹配set -o rematchpcre
:但是,对每个文件(包括
bad
目录中的文件)的 shell 代码的评估可能会比其他解决方案慢很多。还要注意 PCRE(与 zsh glob 相反)会阻塞在区域设置中不形成有效字符的字节序列,并且不支持 UTF-8 以外的多字节字符集。将区域设置固定为
C
喜欢find
上述内容将解决此特定模式的问题。如果您
[[ =~ ]]
只想像 in 那样进行扩展正则表达式匹配bash
,您也可以只加载 pcre 模块 (zmodload zsh/pcre
) 并使用[[ -pcre-match ]]
而不是[[ =~ ]]
进行 PCRE 匹配。或者您可以使用
grep -zP
(假设 GNUgrep
或兼容)进行过滤:(尽管
find
仍然发现所有目录中的所有bad
文件)。如果您需要对这些文件执行任何操作(每行打印一个除外),请替换
tr '\0' '\n'
为。xargs -r0 cmd
¹ 在任何情况下,我都不知道任何
find
支持类似 perl 或类似 vim 的正则表达式的实现,您需要环视运算符。您不需要正则表达式,您可以使用
-path
谓词在任何级别排除具有特定名称的目录虽然它可能效率较低(尽管我不确定!)并且比
find
's 强大的过滤更“正确”(例如grep
,这里的天真不适用于包含换行符的名称,尽管这些非常罕见并且通常表示错误) ,通常更容易堆叠几个实例,grep
这些实例使用更简单的匹配和反向匹配依次过滤结果-v
这需要对子字符串更加谨慎,以确保您确实找到了目录名称,但通常会提供更容易理解的语法,并且可以满足您的所有需求!