find
(para os predicados -name
/ -path
padrã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á find
de 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 3
com algumas find
implementaçõ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*bar
atual¹ 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 find
se 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 f
e a maioria dos outros find
predicados), 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 oN
lá para ignorar a classificação como com find
, D
para incluir dot-files (não se aplica a este glob))
To Para find
rastrear 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*bar
os 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).
-path
ou-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?