CP: nombre maximum de fichiers source arguments pour l'utilitaire de copie


11

Considérez qu'il y a un nombre incalculable de fichiers sous / src /

cp /src/* /dst/

Combien de fichiers cpseront traités avec succès?


2
Si la liste d'arguments est trop longue (rappelez-vous, ce que * fait est de développer une liste de tous les fichiers qui correspondent au glob), vous pouvez la contourner en utilisant par exemple IFS="\n" for file in /src/*; do mv "$file" /dst/; doneou rsync -a /src/ /dst/.
DopeGhoti

Réponses:


18

Cela dépend grandement du système et de la version, du nombre et de la taille des arguments et du nombre et de la taille des noms de variables d'environnement.

Traditionnellement sur Unix, la limite (telle que rapportée par getconf ARG_MAX) était plus ou moins sur la taille cumulée de:

  • La longueur des chaînes d'arguments (y compris la terminaison '\0')
  • La longueur du tableau de pointeurs vers ces chaînes, donc généralement 8 octets par argument sur un système 64 bits
  • La longueur des chaînes d'environnement (y compris la terminaison '\0'), une chaîne d'environnement étant par convention quelque chose comme var=value.
  • La longueur du tableau de pointeurs vers ces chaînes, donc généralement 8 octets par argument sur un système 64 bits

Gardant à l'esprit que cela cpcompte également comme argument (est le premier argument).

Sous Linux, cela dépend de la version. Le comportement a changé récemment là où ce n'est plus un espace fixe.

La vérification sous Linux 3.11, getconf ARG_MAXrapporte désormais un quart de la limite définie sur la taille de la pile, ou 128 ko si c'est moins de 512 ko).

( zshsyntaxe ci-dessous):

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

Cette limite est sur la taille cumulée des chaînes d'argument et d'environnement et certains frais généraux (je soupçonne en raison de la considération d'alignement sur les limites de page). La taille des pointeurs n'est pas prise en compte.

En cherchant la limite, j'obtiens:

$ /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

La taille cumulée maximale avant rupture dans ce cas est:

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

Maintenant, cela ne signifie pas que vous pouvez passer 1 million d'arguments vides. Sur un système 64 bits, 1 million d'arguments vides font une liste de pointeurs de 8 Mo, ce qui serait supérieur à ma taille de pile de 4 Mo.

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

(vous aurez remarqué que ce n'est pas une erreur E2BIG. Je ne sais pas à quel moment le processus y est tué, si c'est dans l' execveappel système ou plus tard).

Notez également (toujours sous Linux 3.11) que la taille maximale d'un seul argument ou chaîne d'environnement est de 128 Ko, quelle que soit la taille de la pile.

$ /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

Pouvez-vous partager s'il vous plaît, comment avez-vous trouvé le 164686numéro? c'est-à-dire comment avez-vous calculé que la séquence serait 2097152inférieure à la taille ARG_MAX?
Sergiy Kolodyazhnyy

14

Cela dépendra de la valeur de ARG_MAX qui peut changer entre les systèmes. Pour connaître la valeur de l'exécution de votre système (en montrant le résultat sur le mien à titre d'exemple):

$ getconf ARG_MAX
2097152

Cela n'a rien à voir avec cpou votre shell, c'est une limite imposée par le noyau, il n'exécutera pas de exec()commandes ( ) si leurs arguments sont plus longs que ARG_MAX. Ainsi, si la longueur de la liste d'arguments à laquelle vous avez donné cpest supérieure à ARG_MAX, la cpcommande ne s'exécutera pas du tout.

Pour répondre à votre question principale alors, cpne traitera aucun fichier car il ne sera jamais exécuté avec autant d'arguments. Je dois également mentionner que cela ne dépend pas du nombre d'arguments mais de leur longueur. Vous pourriez éventuellement avoir le même problème avec des noms de fichiers très rares mais très longs.


La façon de contourner ces erreurs consiste à exécuter votre commande en boucle:

for file in /src/*; do cp "$file" /dst/; done

Cela signifie-t-il que même des langues de niveau inférieur comme CARG_MAX peuvent avoir des problèmes et des noms de fichiers très longs?
Harold Fischer
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.