“ Liste darguments trop longue ”: Comment y faire face, sans changer ma commande?

Lorsque jexécute une commande comme ls */*/*/*/*.jpg, jobtiens lerreur

-bash: /bin/ls: Argument list too long 

Je sais pourquoi cela se produit: cest parce quil y a une limite du noyau sur la quantité despace pour les arguments dune commande. Le conseil standard est de changer la commande que jutilise, pour éviter de nécessiter autant despace pour les arguments (par exemple, utilisez find et xargs).

Que faire si je ne veux pas changer la commande? Que faire si je veux continuer à utiliser la même commande? Comment puis-je faire que les choses « fonctionnent simplement », sans obtenir cette erreur? Quelles solutions sont disponibles?

Commentaires

  • Lecture utile: FAQ Bash 95 . Sans changer votre commande il ny a pas grand-chose à faire ‘ à part recompiler pour augmenter la taille maximale de votre liste darguments, ou modifier la structure de vos répertoires pour quil y ait moins de fichiers.
  • @ jw013 basé sur la version du noyau Linux, il peut être possible daugmenter la liste des arguments – voir unix.stackexchange.com/a/45161/8979 pour plus de détails sur le changement de systèmes récents.
  • @UlrichDangel, oui, cest possible! Voir ma réponse; ma réponse montre comment le faire (sur L inux, avec un noyau suffisamment récent).

Réponse

Sous Linux, la quantité maximale despace pour la commande arguments représente 1 / 4e de la quantité despace de pile disponible. Donc, une solution consiste à augmenter la quantité despace disponible pour la pile.

Version courte: exécutez quelque chose comme

ulimit -s 65536 

Version plus longue : La quantité despace disponible par défaut pour la pile est de 8192 Ko. Vous pouvez voir la quantité despace disponible, comme suit:

$ ulimit -s 8192 

Choisissez un nombre plus grand et définissez la quantité despace disponible pour la pile. Par exemple, si vous voulez essayer dautoriser jusquà 65536 Ko pour la pile, exécutez ceci:

$ ulimit -s 65536 

Vous devrez peut-être jouer avec la taille de ce besoin être, en utilisant des essais et des erreurs. Dans de nombreux cas, il sagit dune solution rapide et efficace qui éliminera le besoin de modifier la commande et de définir la syntaxe de find, xargs, etc. (bien que je réalise quil y a dautres avantages à le faire).

Je pense que cest spécifique à Linux. Je soupçonne que cela naidera probablement pas sur tout autre système dexploitation Unix (non testé).

Commentaires

  • Vous pouvez vérifier comme ça que cela a fonctionné : $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
  • Cela signifie-t-il que si je rend la taille de pile illimitée avec ulimit -s unlimited, la taille de la ligne de commande sera illimité aussi?

Réponse

Au lieu de ls */*/*/*/*.jpg, essayez:

echo */*/*/*/*.jpg | xargs ls 

xargs (1) sait quel est le nombre maximum darguments sur le système, et divisera son entrée standard pour appeler la ligne de commande spécifiée plusieurs fois sans plus darguments que cette limite, quelle quelle soit (vous pouvez également la définir inférieure au maximum du système dexploitation en utilisant le -n).

Par exemple, supposons que la limite soit de 3 arguments et que vous ayez cinq fichiers. Dans ce cas, xargs exécutera ls deux fois:

  1. ls 1.jpg 2.jpg 3.jpg
  2. ls 4.jpg 5.jpg

Souvent, cela convient parfaitement, mais pas toujours – par exemple, vous ne pouvez pas comptez sur le ls (1) tri de toutes les entrées pour vous correctement, car chaque ls -invocation distincte triera uniquement le sous-ensemble dentrées qui lui est donné par xargs.

Bien que vous puissiez augmenter la limite comme suggéré par dautres, il y aura toujours une limite – et un jour votre collection JPG la dépassera à nouveau. Vous devez préparer votre (vos) script (s) à traiter un nombre infini …

Commentaires

  • Merci pour lidée! Ce nest pas une mauvaise solution de contournement. Deux mises en garde: 1. Cela casse sur les répertoires et les noms de fichiers qui ont des espaces dans leur nom, donc ce ‘ nest pas un substitut parfait. 2. Cela va-t-il rencontrer le même problème avec Argument list too long, mais pour echo au lieu de ls, sur les shells où echo nest pas une commande intégrée au shell? (Peut-être que ‘ nest pas un problème dans la plupart des shells, alors peut-être que ‘ nest pas pertinent.)
  • Oui , les caractères spéciaux dans les noms de fichiers posent problème. Le mieux est dutiliser find avec le prédicat -print0 – et de diriger sa sortie vers xargs avec loption -0.echo est un shell intégré et ne souffre pas de la limitation de ligne de commande de exec (3).
  • Cela fonctionne avec les commandes qui attendent largument variable comme dernier paramètre, comme pour ls, mais que dois-je faire quand je veux mv plusieurs fichiers dans un seul répertoire, par exemple mv * destdir? Si * donne lerreur  » trop darguments « , je peux ‘ t faire xargs passer les chemins en tant que premier à mv dune manière ou dune autre, ou puis-je?
  • Consultez la page de manuel xargs sur votre système – sur FreeBSD, par exemple, -J vous aidera vous avec cette tâche. Si sur votre système dexploitation il ny a aucun moyen de faire cela, vous ‘ devrez écrire un script personnalisé pour réorganiser les arguments. Quelque chose comme: destdir=$1; shift; mv "$@" "$destdir". Donnez ensuite ce nouveau script à xargs: .... | xargs newscript $destdir

Réponse

Cet article du Linux Journal donne 4 solutions. Seule la quatrième solution nimplique pas de changer la commande:

La méthode n ° 4 consiste à augmenter manuellement le nombre de pages allouées dans le noyau pour la ligne de commande arguments. Si vous regardez le fichier include / linux / binfmts.h, vous trouverez ce qui suit vers le haut:

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

Afin daugmenter la quantité de mémoire dédié aux arguments de la ligne de commande, il vous suffit de fournir la valeur MAX_ARG_PAGES avec un nombre plus élevé. Une fois cette modification enregistrée, recompilez, installez et redémarrez simplement dans le nouveau noyau comme vous le feriez normalement.

Sur mon propre système de test, jai réussi à résoudre tous mes problèmes en élevant cette valeur à 64. en test, je nai pas rencontré un seul problème depuis le passage. Ceci est tout à fait normal puisque même avec MAX_ARG_PAGES défini sur 64, la ligne de commande la plus longue possible que je pourrais produire noccuperait que 256 Ko de mémoire système – pas beaucoup selon les normes matérielles système actuelles .

Les avantages de la méthode n ° 4 sont clairs. Vous pouvez maintenant simplement exécuter la commande comme vous le feriez normalement, et elle se termine avec succès. Les inconvénients sont tout aussi évidents. Si vous augmentez la quantité de mémoire disponible à la ligne de commande au-delà de la quantité de mémoire système disponible, vous pouvez créer une attaque DOS sur votre propre système et le faire planter. Sur les systèmes multi-utilisateurs en particulier, même une petite augmentation peut avoir un impact significatif car chaque utilisateur se voit alors attribuer de mémoire supplémentaire. Par conséquent, testez toujours de manière approfondie dans votre propre environnement, car cest le moyen le plus sûr de déterminer si la méthode n ° 4 est une option viable pour vous.

Je reconnais que la limitation est sérieusement ennuyeuse.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *