Cuando ejecuto un comando como ls */*/*/*/*.jpg
, aparece el error
-bash: /bin/ls: Argument list too long
Sé por qué sucede esto: es porque hay un límite de kernel en la cantidad de espacio para argumentos de un comando. El consejo estándar es cambiar el comando que uso, para evitar requerir tanto espacio para los argumentos (por ejemplo, use find
y xargs
).
¿Qué pasa si no quiero cambiar el comando? ¿Qué pasa si quiero seguir usando el mismo comando? ¿Cómo puedo hacer que las cosas «simplemente funcionen» sin que aparezca este error? ¿Qué soluciones hay disponibles?
Comentarios
- Lectura útil: Bash FAQ 95 . Sin cambiar su comando ‘ no hay mucho que pueda hacer además de recompilar para aumentar el tamaño máximo de su lista de argumentos, o cambiar la estructura de su directorio para que haya menos archivos.
- @ jw013 basado en la versión del kernel de Linux, es posible aumentar la lista de argumentos; consulte unix.stackexchange.com/a/45161/8979 para obtener detalles sobre el cambio en sistemas recientes.
- @UlrichDangel, ¡Sí, es posible! Vea mi respuesta; mi respuesta muestra cómo hacerlo (en L inux, con un kernel lo suficientemente reciente).
Respuesta
En Linux, la cantidad máxima de espacio para el comando argumentos es 1/4 de la cantidad de espacio de pila disponible. Entonces, una solución es aumentar la cantidad de espacio disponible para la pila.
Versión corta: ejecute algo como
ulimit -s 65536
Versión más larga : La cantidad predeterminada de espacio disponible para la pila es algo así como 8192 KB. Puede ver la cantidad de espacio disponible, de la siguiente manera:
$ ulimit -s 8192
Elija un número mayor y establezca la cantidad de espacio disponible para la pila. Por ejemplo, si desea intentar permitir hasta 65536 KB para la pila, ejecute esto:
$ ulimit -s 65536
Es posible que deba jugar con el tamaño que necesita ser, usando prueba y error. En muchos casos, esta es una solución rápida y sucia que eliminará la necesidad de modificar el comando y resolver la sintaxis de find
, xargs
, etc. (aunque me doy cuenta de que hay otros beneficios al hacerlo).
Creo que esto es específico de Linux. Sospecho que probablemente no ayudará en ningún otro sistema operativo Unix (no probado).
Comentarios
- Puede verificar así que funcionó : $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
- ¿Significa esto que si hago que el tamaño de la pila sea ilimitado con
ulimit -s unlimited
el tamaño de la línea de comandos será ¿ilimitado también?
Responder
En lugar de ls */*/*/*/*.jpg
, intente:
echo */*/*/*/*.jpg | xargs ls
xargs
(1) sabe cuál es el número máximo de argumentos en el sistema y dividirá su entrada estándar para llamar a la línea de comando especificada varias veces sin más argumentos que ese límite, cualquiera que sea (también puede establecerlo por debajo del máximo del sistema operativo utilizando -n
opción).
Por ejemplo, suponga que el límite es de 3 argumentos y tiene cinco archivos. En ese caso, xargs
ejecutará ls
dos veces:
-
ls 1.jpg 2.jpg 3.jpg
-
ls 4.jpg 5.jpg
A menudo, esto es perfectamente adecuado, pero no siempre; por ejemplo, no puede confíe en ls
(1) ordenar todas las entradas correctamente, porque cada ls
-invocación clasificará solo el subconjunto de entradas que le proporcione xargs
.
Aunque puede superar el límite según lo sugerido por otros, todavía habrá un límite: y algún día tu colección JPG volverá a superarla. Debes preparar tu (s) script (s) para tratar con un número infinito …
Comentarios
- ¡Gracias por la idea! Esta no es una mala solución. Dos advertencias: 1. Esto rompe en directorios y nombres de archivos que tienen espacios en su nombre, por lo que ‘ no es un sustituto perfecto. 2. ¿Se encontrará con el mismo problema con
Argument list too long
, pero paraecho
en lugar dels
, en shells dondeecho
no es un comando integrado en el shell? (Tal vez ese ‘ no sea un problema en la mayoría de los shells, así que tal vez ese ‘ sea irrelevante). - Sí , los caracteres especiales en los nombres de archivo son un problema. Lo mejor que puede hacer es usar
find
con el predicado-print0
y canalizar su salida axargs
con la opción-0
.echo
es un shell integrado y no sufre la limitación de la línea de comandos deexec
(3). - Esto funciona con comandos que esperan el argumento de la variable como último parámetro, como
ls
, pero ¿qué hago cuando quieromv
muchos archivos en un solo directorio, por ejemplomv * destdir
? Si*
da el error » demasiados argumentos «, puedo ‘ t hacerxargs
pasar las rutas como la primera amv
de alguna manera, ¿o puedo? - Revise la página de manual para
xargs
en su sistema; en FreeBSD, por ejemplo,-J
ayudará usted con esta tarea. Si en su sistema operativo no hay forma de hacer esto, ‘ necesitará escribir un script personalizado para reordenar los argumentos. Algo como:destdir=$1; shift; mv "$@" "$destdir"
. Luego, entregue este nuevo script axargs
:.... | xargs newscript $destdir
Responder
Este artículo de Linux Journal ofrece 4 soluciones. Solo la cuarta solución no implica cambiar el comando:
El método # 4 implica aumentar manualmente el número de páginas que se asignan dentro del kernel para la línea de comandos argumentos. Si observa el archivo include / linux / binfmts.h, encontrará lo siguiente cerca de la parte superior:
/* * MAX_ARG_PAGES defines the number of pages allocated for arguments * and envelope for the new program. 32 should suffice, this gives * a maximum env+arg of 128kB w/4KB pages! */ #define MAX_ARG_PAGES 32
Para aumentar la cantidad de memoria dedicado a los argumentos de la línea de comandos, simplemente debe proporcionar el valor MAX_ARG_PAGES con un número más alto. Una vez guardada esta edición, simplemente vuelva a compilar, instalar y reiniciar en el nuevo kernel como lo haría normalmente.
En mi propio sistema de prueba logré resolver todos mis problemas elevando este valor a 64. Después de un extenso pruebas, no he experimentado un solo problema desde el cambio. Esto es completamente esperado ya que incluso con
MAX_ARG_PAGES
configurado en 64, la línea de comando más larga posible que podría producir solo ocuparía 256 KB de memoria del sistema, no mucho para los estándares de hardware del sistema de hoy .Las ventajas del Método # 4 son claras. Ahora puede simplemente ejecutar el comando como lo haría normalmente, y se completa correctamente. Las desventajas son igualmente claras. Si aumenta la cantidad de memoria disponible a la línea de comandos más allá de la cantidad de memoria del sistema disponible, puede crear un ataque DOS en su propio sistema y hacer que se bloquee. En sistemas multiusuario en particular, incluso un pequeño aumento puede tener un impacto significativo porque a cada usuario se le asigna el memoria adicional. Por lo tanto, realice siempre pruebas exhaustivas en su propio entorno, ya que esta es la forma más segura de determinar si el Método 4 es una opción viable para usted.
Estoy de acuerdo en que la limitación es muy molesta.