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 find
y grep
que 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 find
expresiones que no conozco? ¿O hay una opción para find
hacer coincidir el glob sin hacer coincidir el mismo glob en un subdirectorio (por ejemplo, foo/*.jpg
no está permitido hacer coincidir bar/foo/*.jpg
)?
-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?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-much
puede producir un error,for f in glob-that-matches-too-much
no lo hace, por lo que puede hacer lo siguiente:El bucle puede ser extremadamente lento, pero debería funcionar.
O:
(
printf
estando 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
something
conecho
debería hacerlo.printf
: será más rápido que llamarecho
miles 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
.printf
está integrada, y los shells presumiblemente usan el mismo método para proporcionarle los argumentos que usan para enumerar los argumentosfor
.cat
No es una construcción.mksh
dondeprintf
no está incorporado y conchas comoksh93
dondecat
está (o puede estar) incorporado. Ver tambiénzargs
enzsh
el trabajo alrededor de ella sin tener que recurrir axargs
.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 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áfind
de 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 3
con algunasfind
implementaciones). 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*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 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 f
y la mayoría de los otrosfind
predicados), por ejemplo:(
(|.bak)
es un operador glob contrario a{,.bak}
, el(.)
calificador glob es el equivalente defind
's-type f
, agregueoN
allí para omitir la clasificación como confind
,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:Es decir, pode todos los directorios en el nivel 1 excepto
foo*bar
los 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.bak
y 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
sh
script POSIX para convertir el globo a unafind
expresión:Para usarse con un
sh
globo 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 veadir
igual que para un patrón.fuente