Liste d'arguments trop longue

Résolu/Fermé
gnugo - 13 févr. 2012 à 19:52
 Smux - 30 mars 2017 à 09:42
Bonjour,

j'ai un problème : je suis très limité sur le nombre d'arguments de mes scripts
Alors que d'autres commandes peuvent !
Comme "echo"

Pour l'illustrer, j'ai créé 54001 fichiers :

test:$ cd TEST/
TEST:$ ll | wc
54001 486002 6515795
TEST:$ echo * >/dev/null
TEST:$ touch script
TEST:$ chmod +x script
TEST:$ ./script *
bash: ./script: Liste d'arguments trop longue
TEST:$

"echo" y arrive sans erreur, alors pourquoi pas un script ?
Puis-je remédier à ce problème ?
Merci

11 réponses

mamiemando Messages postés 33073 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 16 avril 2024 7 748
13 févr. 2012 à 20:19
C'est par ce que le caractère * est substitué par un ensemble de noms de fichiers qui comporte trop d'éléments (trop de fichiers). Pour fixer les idées, on va dire qu'au lieu du script, je veux instancier la commande rm sur un grand nombre de fichiers présents dans un même répertoire.

Mettons que j'aie 100 000 fichiers (je dis un nombre au pif) dans un répertoire et que je lance "rm *". Ça ne marchera pas, j'aurais le même message d'erreur.

mkdir toto
cd toto
for x in $(seq 1 100000); do touch $x; done


Pour m'en sortir je peux lancer :

for x in $(ls -1); do rm $x; done


Cette version instancie 100 000 fois le programme rm, donc ce n'est pas forcément ce qu'on veut (on peut souhaiter que le fichier itère sur les 100 000 fichiers reçus en paramètre). On pourrait se dire, pas de soucis avec | et xargs on va s'en sortir car on ne mentionne plus explicitement le meta caractère "*" :

ls -1 | xargs rm


En fait il y a de fortes chances que ce soit le même problème, car cette commande va passer en ligne mes 100 000 fichiers à rm.

Tu noteras que le problème ne se pose pas avec ton exemple "ll | wc" puisque le meta caractère * n'est pas présent (donc pas substitué) : ici on applique la commande wc à un flux engendré par la commande ll, qui peut sans problème écrire un très grand nombre de fichier dans la sortie standard. Ce flux peut ensuite être vu comme un grand fichier texte que l'on passerait à la commande wc. Quoi qu'il en soit, on n'a pas passé un grand nombre d'arguments à aucune des deux commandes, donc il n'est normal qu'il n'y ait pas de message d'erreur. Par contre avec un "ll * | wc", tu auras eu le problème.

Ce qui est plus bizarre, c'est que tu devrais avoir le même problème avec echo. Mais si le message d'erreur est écrit dans /dev/stdout ta redirection absorbe le message d'erreur (qui en toute rigueur devrait être écrit dans /dev/stderr). Pour être sûr il faudrait voir ce que la commande "echo *" donne, mais c'est peut être l'explication dans ton cas...

Dans ton cas il y a plusieurs solutions
- créer plusieurs répertoires avec nombre restreint de fichiers
- invoquer ton script au travers d'une boucle for (si ça a du sens par rapport à ce que doit faire le script) sur chaque fichier présent dans le répertoire
- passer en argument de ton script le répertoire sur lequel il doit travailler pour éviter de passer en paramètre un grand nombre de paramètres

Bonne chance
2
Merci
0