find(对于-name/ -path标准谓词)与通配符一样使用通配符模式(请注意,{a,b}它不是通配符运算符;展开后,将得到两个通配符)。主要区别在于对斜杠(以及未在中特别处理的点文件和目录find)的处理。*在全球范围内不会跨越几个目录。*/*/*将导致最多列出2级目录。添加a -path './*/*/*'将匹配至少3层深度的任何文件,并且不会停止find列出任何深度的任何目录的内容。
对于那个特殊的
./foo*bar/quux[A-Z]{.bak,}/pic[0-9][0-9][0-9][0-9]?.jpg
几个问题,翻译起来很容易,您想要目录3的深度,因此可以使用:
find . -mindepth 3 -maxdepth 3 \
\( -path './foo*bar/quux[A-Z].bak/pic[0-9][0-9][0-9][0-9]?.jpg' -o \
-path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg' \) \
-exec cmd {} +
(或-depth 3带有某些find实现)。或POSIXly:
find . -path './*/*/*' -prune \
\( -path './foo*bar/quux[A-Z].bak/pic[0-9][0-9][0-9][0-9]?.jpg' -o \
-path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg' \) \
-exec cmd {} +
这将保证那些*和字符?不能匹配/。
(find,与glob相反,它将读取foo*bar当前目录¹中目录以外的目录的内容,而不对文件列表进行排序。但是,如果撇开/ ,无效字符[A-Z]的行为或*/ 的问题?是未指定,您将获得相同的文件列表)。
但是无论如何,正如@muru所示,find如果只是将文件列表分成多个运行以解决execve()系统调用的限制,则无需求助。某些外壳(如zsh(带有zargs)或ksh93(带有command -x))甚至对此具有内置支持。
用zsh(其glob也具有-type f和find谓词等价的谓词),例如:
autoload zargs # if not already in ~/.zshrc
zargs ./foo*bar/quux[A-Z](|.bak)/pic[0-9][0-9][0-9][0-9]?.jpg(.) -- cmd
((|.bak)与glob运算符相反{,.bak},(.)glob限定符与finds 等效-type f,oN在其中添加以跳过与的排序find,D包括点文件(不适用于此glob))
¹要find像globs一样爬网目录树,您需要类似以下内容:
find . ! -name . \( \
\( -path './*/*' -o -name 'foo*bar' -o -prune \) \
-path './*/*/*' -prune -name 'pic[0-9][0-9][0-9][0-9]?.jpg' -exec cmd {} + -o \
\( ! -path './*/*' -o -name 'quux[A-Z]' -o -name 'quux[A-Z].bak' -o -prune \) \)
也就是说,修剪所有级别为1的目录(除去目录)foo*bar,以及所有级别2的除quux[A-Z]或quux[A-Z].bak,然后选择pic...级别3的目录(并修剪该级别的所有目录)。
-path或一起使用-ipath。find . -path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg'应该工作-除了匹配/fooz/blah/bar/quuxA/pic1234d.jpg。那会是个问题吗?