find
(para os predicados padrão -name
/ -path
) usa padrões curinga assim 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 de ponto e diretórios não sendo tratados especialmente em find
). *
em globs não abrangerá vários diretórios. */*/*
fará com que até 2 níveis de diretórios sejam listados. Adicionar -path './*/*/*'
corresponderá a todos os arquivos com pelo menos 3 níveis de profundidade e não impedirá que find
liste 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ê está querendo diretórios na profundidade 3, então você pode 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 implementações find
). 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 que os *
e ?
não poderiam corresponder a /
caracteres.
( find
, ao contrário de globs, leria o conteúdo de diretórios diferentes de foo*bar
no diretório atual¹, e não ordenaria a lista de arquivos. Mas se deixarmos de lado o problema de que o que é correspondido por [A-Z]
ou o comportamento de *
/ ?
em relação a caracteres inválidos não é especificado, você obterá a mesma lista de arquivos).
Mas, em qualquer caso, como @muru mostrou , não é necessário recorrer a find
se for apenas dividir a lista de arquivos em várias execuções para contornar o limite da chamada do sistema execve()
. Alguns shells como zsh
(com zargs
) ou ksh93
(com command -x
) ainda têm suporte embutido para isso.
Com zsh
(cujas globs também têm o equivalente a -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 ao contrário de {,.bak}
, o qualificador (.)
glob é o equivalente de find
' -type f
, adicione oN
lá para ignorar a classificação como find
, D
para incluir arquivos de pontos (não se aplica a este glob))
¹ Para find
rastrear a árvore de diretórios, como acontece com globs, você precisa de 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 é podar todos os diretórios no nível 1, exceto os foo*bar
e todos no nível 2, exceto os quux[A-Z]
ou quux[A-Z].bak
e, em seguida, selecionar pic...
em nível 3 (e podar todos os diretórios a esse nível).