Una y otra vez tuve este problema: tengo un problema, que coincide exactamente con los archivos correctos, pero causa Command line too long. Cada vez que lo he convertido en una combinación de findy grepque funciona para la situación particular, pero que no es 100% equivalente.
Por ejemplo:
./foo*bar/quux[A-Z]{.bak,}/pic[0-9][0-9][0-9][0-9]?.jpg
¿Existe una herramienta para convertir globos en findexpresiones que no conozco? ¿O hay una opción para findhacer coincidir el glob sin hacer coincidir el mismo glob en un subdirectorio (por ejemplo, foo/*.jpgno está permitido hacer coincidir bar/foo/*.jpg)?

-patho-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?echo <glob> | cat, suponiendo que yo sepa bash, echo estáRespuestas:
Si el problema es que obtiene un error argumento-lista-es-demasiado-largo, use un bucle o un shell incorporado. Si bien
command glob-that-matches-too-muchpuede producir un error,for f in glob-that-matches-too-muchno lo hace, por lo que puede hacer lo siguiente:El bucle puede ser extremadamente lento, pero debería funcionar.
O:
(
printfestando integrado en la mayoría de los shells, lo anterior funciona alrededor de la limitación de laexecve()llamada al sistema)También funciona con bash. Sin embargo, no estoy seguro exactamente dónde está documentado esto.
Tanto Vim
glob2regpat()como Pythonfnmatch.translate()pueden convertir globos en expresiones regulares, pero ambos también se usan.*para*, coincidiendo/.fuente
somethingconechodebería hacerlo.printf: será más rápido que llamarechomiles de veces y ofrece más flexibilidad.exec, que se aplica a comandos externos comocat; pero ese límite no se aplica a comandos integrados de shell comoprintf.printfestá integrada, y los shells presumiblemente usan el mismo método para proporcionarle los argumentos que usan para enumerar los argumentosfor.catNo es una construcción.mkshdondeprintfno está incorporado y conchas comoksh93dondecatestá (o puede estar) incorporado. Ver tambiénzargsenzshel trabajo alrededor de ella sin tener que recurrir axargs.find(para los predicados-name/-pathestá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 enfind).*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áfindde enumerar el contenido de ningún directorio a ninguna profundidad.Para ese particular
un par de globos, es fácil de traducir, quieres directorios en profundidad 3, por lo que puedes usar:
(o
-depth 3con algunasfindimplementaciones). O POSIXY: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 defoo*barlos 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
findsi es solo para dividir la lista de archivos en varias ejecuciones para evitar el límite de laexecve()llamada del sistema. Algunos proyectiles comozsh(conzargs) oksh93(concommand -x) incluso tienen soporte incorporado para eso.Con
zsh(cuyos globos también tienen el equivalente-type fy la mayoría de los otrosfindpredicados), por ejemplo:(
(|.bak)es un operador glob contrario a{,.bak}, el(.)calificador glob es el equivalente defind's-type f, agregueoNallí para omitir la clasificación como confind,Dpara incluir archivos de puntos (no se aplica a este glob))¹ Para
findrastrear el árbol de directorios como lo harían los globos, necesitarías algo como:Es decir, pode todos los directorios en el nivel 1 excepto
foo*barlos y todos en el nivel 2 excepto losquux[A-Z]oquux[A-Z].bak, y luego seleccionepic...los del nivel 3 (y pode todos los directorios en ese nivel).fuente
Puede escribir una expresión regular para encontrar que coincida con sus requisitos:
fuente
., añadir el partido opcional para.baky el cambio*a[^/]*que no coincide con los caminos como / foo / foo / bar, etc.[0-9][0-9][0-9][0-9]?a[0-9]{3,4}Generalizando en la nota de mi otra respuesta , como una respuesta más directa a su pregunta, podría usar este
shscript POSIX para convertir el globo a unafindexpresión:Para usarse con un
shglobo estándar (por lo tanto, no con los dos globos de su ejemplo que usan expansión de llaves ):(eso no ignora los archivos de puntos o los directorios de puntos excepto
.y..y no clasifica la lista de archivos).Que sólo se trabaja con pegotes relativos al directorio actual, sin
.o..componentes. Con un poco de esfuerzo, podría extenderlo a cualquier globo, más que a un globo ... Eso también podría optimizarse para queglob2find 'dir/*'no se veadirigual que para un patrón.fuente