find(para os predicados -name/ -pathpadrão) usa padrões curinga como globs (observe que {a,b}não é um operador glob; após a expansão, você obtém dois globs). A principal diferença é o tratamento de barras (e os arquivos e diretórios de ponto não são tratados especialmente em find). *no globs não abrange vários diretórios. */*/*fará com que até 2 níveis de diretórios sejam listados. A adição de a -path './*/*/*'corresponderá a qualquer arquivo com pelo menos três níveis de profundidade e não deixará findde listar o conteúdo de qualquer diretório em qualquer profundidade.
Para esse particular
./foo*bar/quux[A-Z]{.bak,}/pic[0-9][0-9][0-9][0-9]?.jpg
par de globs, é fácil de traduzir, você quer diretórios na profundidade 3, para poder usar:
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 {} +
(ou -depth 3com algumas findimplementações). Ou 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 {} +
O que garantiria isso *e ?não poderia corresponder aos /caracteres.
( find, ao contrário dos globs, leria o conteúdo de diretórios diferentes dos do diretório foo*baratual¹ e não classificaria a lista de arquivos. Mas, se deixarmos de lado o problema de que o que corresponde [A-Z]ou o comportamento de */ ?com relação a caracteres inválidos é não especificado, você obterá a mesma lista de arquivos).
Mas, em qualquer caso, como o @muru mostrou , não há necessidade de recorrer findse for apenas para dividir a lista de arquivos em várias execuções para contornar o limite da execve()chamada do sistema. Algumas conchas como zsh(com zargs) ou ksh93(com command -x) têm suporte embutido para isso.
With zsh(cujos globos também têm o equivalente -type fe a maioria dos outros findpredicados), por exemplo:
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)É um operador glob contrário a {,.bak}, o (.)glob qualificador é o equivalente do find's -type f, adicione oNlá para ignorar a classificação como com find, Dpara incluir dot-files (não se aplica a este glob))
To Para findrastrear a árvore de diretórios como os globs precisariam, seria necessário algo como:
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 \) \)
Isso remove todos os diretórios no nível 1, exceto foo*baros e todos no nível 2, exceto os quux[A-Z]ou quux[A-Z].bak, e então seleciona pic...os no nível 3 (e remove todos os diretórios nesse nível).
-pathou-ipath.find . -path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg'deve funcionar - exceto que corresponderá/fooz/blah/bar/quuxA/pic1234d.jpg. Isso será um problema?