find
(para los predicados -name
/ -path
estándar) utiliza patrones comodín al igual que los globos (tenga en cuenta que {a,b}
no es un operador de globo; después de la expansión, obtiene dos globos). La principal diferencia es el manejo de barras (y los archivos de puntos y directorios que no se tratan especialmente en find
). *
en globos no abarcará varios directorios. */*/*
hará que se enumeren hasta 2 niveles de directorios. Agregar un -path './*/*/*'
archivo coincidirá con cualquier archivo que tenga al menos 3 niveles de profundidad y no dejará find
de enumerar el contenido de ningún directorio a ninguna profundidad.
Para ese particular
./foo*bar/quux[A-Z]{.bak,}/pic[0-9][0-9][0-9][0-9]?.jpg
un par de globos, es fácil de traducir, quieres directorios en profundidad 3, por lo que puedes 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 {} +
(o -depth 3
con algunas find
implementaciones). O POSIXY:
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 {} +
Lo que garantizaría que esos *
y ?
no podían coincidir con los /
personajes
( find
, a diferencia de los globos, leería el contenido de directorios distintos de foo*bar
los del directorio actual¹, y no ordenaría la lista de archivos. Pero si dejamos de lado el problema de que lo que coincide [A-Z]
o el comportamiento de *
/ ?
con respecto a los caracteres no válidos es sin especificar, obtendría la misma lista de archivos).
Pero en cualquier caso, como ha demostrado @muru , no hay necesidad de recurrir find
si es solo para dividir la lista de archivos en varias ejecuciones para evitar el límite de la execve()
llamada del sistema. Algunos proyectiles como zsh
(con zargs
) o ksh93
(con command -x
) incluso tienen soporte incorporado para eso.
Con zsh
(cuyos globos también tienen el equivalente -type f
y la mayoría de los otros find
predicados), por ejemplo:
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)
es un operador glob contrario a {,.bak}
, el (.)
calificador glob es el equivalente de find
's -type f
, agregue oN
allí para omitir la clasificación como con find
, D
para incluir archivos de puntos (no se aplica a este glob))
¹ Para find
rastrear el árbol de directorios como lo harían los globos, necesitarías 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 \) \)
Es decir, pode todos los directorios en el nivel 1 excepto foo*bar
los y todos en el nivel 2 excepto los quux[A-Z]
o quux[A-Z].bak
, y luego seleccione pic...
los del nivel 3 (y pode todos los directorios en ese nivel).
-path
o-ipath
.find . -path './foo*bar/quux[A-Z]/pic[0-9][0-9][0-9][0-9]?.jpg'
debería funcionar, excepto que coincidirá/fooz/blah/bar/quuxA/pic1234d.jpg
. será eso un problema?