CP: número máximo de archivos de origen argumentos para la utilidad de copia

11

Tenga en cuenta que hay innumerables archivos en / src /

cp /src/* /dst/

¿Cuántos archivos cpse procesarán con éxito?

Miguel
fuente
2
Si la lista de argumentos es demasiado larga (recuerde, lo que * hace es expandirse a una lista de todos los archivos que coinciden con el glob), puede evitarlo usando eg IFS="\n" for file in /src/*; do mv "$file" /dst/; doneo rsync -a /src/ /dst/.
DopeGhoti

Respuestas:

18

Eso depende en gran medida del sistema y la versión, del número y el tamaño de los argumentos y del número y tamaño de los nombres de las variables de entorno.

Tradicionalmente en Unix, el límite (según lo informado por getconf ARG_MAX) era más o menos en el tamaño acumulativo de:

  • La longitud de las cadenas de argumentos (incluida la terminación '\0')
  • La longitud de la matriz de punteros a esas cadenas, por lo general, 8 bytes por argumento en un sistema de 64 bits
  • La longitud de las cadenas de entorno (incluida la terminación '\0'), siendo una cadena de entorno por convención algo así var=value.
  • La longitud de la matriz de punteros a esas cadenas, por lo general, 8 bytes por argumento en un sistema de 64 bits

Teniendo en cuenta que cptambién cuenta como argumento (es el primer argumento).

En Linux, depende de la versión. El comportamiento allí cambió recientemente donde ya no es un espacio fijo.

Comprobando en Linux 3.11, getconf ARG_MAXahora informa una cuarta parte del límite establecido en el tamaño de la pila, o 128 KB si es inferior a 512 KB).

( zshsintaxis a continuación):

$ limit stacksize
stacksize       8MB
$ getconf ARG_MAX
2097152
$ limit stacksize 4M
$ getconf ARG_MAX
1048576

Ese límite está en el tamaño acumulativo de las cadenas de argumento y entorno y algunos gastos generales (sospecho que debido a la consideración de alineación en los límites de la página). El tamaño de los punteros no se tiene en cuenta.

Buscando el límite, obtengo:

$ /bin/true {1..164686}
$ /bin/true {1..164687}
zsh: argument list too long: /bin/true
$ x= /bin/true {1..164686}
$ x=1 /bin/true {1..164686}
zsh: argument list too long: /bin/true

El tamaño acumulado máximo antes de romper en ese caso es:

$ (env _=/bin/true x=;print -l /bin/true {1..164686}) | wc -c
1044462

Ahora, eso no significa que pueda pasar 1 millón de argumentos vacíos. En un sistema de 64 bits, 1 millón de argumentos vacíos forman una lista de punteros de 8 MB, que estaría por encima de mi tamaño de pila de 4MiB.

$ IFS=:; /bin/true ${=${(l.1000000..:.)${:-}}}
zsh: killed     /bin/true ${=${(l.1000000..:.)${:-}}}

(notará que no es un error E2BIG. No estoy seguro de en qué punto el proceso se anula allí si está dentro de la execvellamada al sistema o más tarde).

También tenga en cuenta (todavía en Linux 3.11) que el tamaño máximo de un solo argumento o cadena de entorno es 128 KB, independientemente del tamaño de la pila.

$ /bin/true ${(l.131071..a.)${:-}} # 131072 OK
$ /bin/true ${(l.131072..a.)${:-}} # 131073 not
zsh: argument list too long: /bin/true
$ /bin/true ${(l.131071..a.)${:-}} ${(l.131071..a.)${:-}} # 2x 131072 OK
Stéphane Chazelas
fuente
¿Puedes compartir, por favor, cómo se te ocurrió el 164686número? es decir, ¿cómo calculó que la secuencia estaría por debajo del 2097152tamaño ARG_MAX?
Sergiy Kolodyazhnyy
14

Eso dependerá del valor de ARG_MAX que puede cambiar entre sistemas. Para averiguar el valor de la ejecución de su sistema (que muestra el resultado en el mío como ejemplo):

$ getconf ARG_MAX
2097152

Esto no tiene nada que ver con cpsu shell, es un límite impuesto por el kernel, no ejecutará ( exec()) comandos si sus argumentos son más largos que ARG_MAX. Entonces, si la longitud de la lista de argumentos que ha dado cpes mayor que ARG_MAX, el cpcomando no se ejecutará en absoluto.

Entonces, para responder a su pregunta principal, cpno procesará ningún archivo, ya que nunca se ejecutará con tantos argumentos. También debo mencionar que esto no depende del número de argumentos sino de su longitud. Posiblemente podría tener el mismo problema con muy pocos pero muy largos nombres de archivo.


La forma de evitar estos errores es ejecutar su comando en un bucle:

for file in /src/*; do cp "$file" /dst/; done
terdon
fuente
¿Esto significa que incluso los lenguajes de nivel inferior como Cpueden tener problemas con ARG_MAX y nombres de archivo realmente largos?
Harold Fischer