OVH Cloud OVH Cloud

Nombre maximal d'arguments

5 réponses
Avatar
lerouzic
Bonjour à tous,

Je suis confronté à un problème qui me plonge dans un abîme de
perplexité. Voilà, j'essaye de passer un grand nombre d'arguments à un
script perl (ces arguments sont des noms de fichier), sous bash (Linux
Debian). J'avais commencé par un petit

./mon_script *.xml

mais quand il y a beaucoup de fichiers, je me retrouve avec une
erreur, due à la limitation de la taille d'une ligne de commande.
Soit, j'ai donc trouvé un dérivatif:

find . -name "*.xml" | xargs ./mon_script

Ici, pas de message d'erreur, mais étrangement, tous les fichiers ne
passent pas. Pour comprendre, j'ai essayé:

find . -name "*.xml" | xargs perl -e 'print $#ARGV . "\n";'

Et ô surprise, j'obtiens:

452
452
452
452
387

Si je comprends bien, le programme est lancé plusieurs fois, avec des
"paquets" de 452 noms de fichiers, jusqu'à ce que tous les fichiers
soient passés. Mais forcément, mon script ne fonctionne pas puisqu'il
est conçu pour recevoir tous les fichiers d'un seul coup.

Avez-vous déja rencontré ce problème (finalement pas si rare puisqu'il
concerne tous les programmes qui nécessitent un grand nombre de
fichiers d'un coup), et connaissez-vous un moyen de le résoudre?
Est-ce une limitation de bash, de xargs ou de perl? Merci d'avance.

Arnaud.

5 réponses

Avatar
Patrick Mevzek

Avez-vous déja rencontré ce problème (finalement pas si rare puisqu'il
concerne tous les programmes qui nécessitent un grand nombre de fichiers
d'un coup), et connaissez-vous un moyen de le résoudre? Est-ce une
limitation de bash, de xargs ou de perl? Merci d'avance.


Cf option -l ou --max-lines de xargs

--
Patrick Mevzek . . . . . . Dot and Co (Paris, France)
<http://www.dotandco.net/> <http://www.dotandco.com/>

Avatar
Laurent Wacrenier
Arnaud écrit:
Avez-vous déja rencontré ce problème (finalement pas si rare puisqu'il
concerne tous les programmes qui nécessitent un grand nombre de
fichiers d'un coup), et connaissez-vous un moyen de le résoudre?
Est-ce une limitation de bash, de xargs ou de perl? Merci d'avance.


C'est une limitation du noyau.
Tu devrais patcher ton script pour qu'il lise la liste des fichiers
sur l'entrées standart. Par exemple :

@ARGV=map{chomp;$_}<> unless @ARGV;

Avatar
no
On Tue, 14 Sep 2004 07:54:33 -0700, Arnaud wrote:

Bonjour à tous,

Je suis confronté à un problème qui me plonge dans un abîme de
perplexité. Voilà, j'essaye de passer un grand nombre d'arguments à un
script perl (ces arguments sont des noms de fichier), sous bash (Linux
Debian). J'avais commencé par un petit

./mon_script *.xml

mais quand il y a beaucoup de fichiers, je me retrouve avec une erreur,
due à la limitation de la taille d'une ligne de commande. Soit, j'ai donc
trouvé un dérivatif:

find . -name "*.xml" | xargs ./mon_script

Ici, pas de message d'erreur, mais étrangement, tous les fichiers ne
passent pas. Pour comprendre, j'ai essayé:

find . -name "*.xml" | xargs perl -e 'print $#ARGV . "n";'

Et ô surprise, j'obtiens:

452
452
452
452
387

Si je comprends bien, le programme est lancé plusieurs fois, avec des
"paquets" de 452 noms de fichiers, jusqu'à ce que tous les fichiers
soient passés. Mais forcément, mon script ne fonctionne pas puisqu'il
est conçu pour recevoir tous les fichiers d'un seul coup.

Avez-vous déja rencontré ce problème (finalement pas si rare puisqu'il
concerne tous les programmes qui nécessitent un grand nombre de fichiers
d'un coup), et connaissez-vous un moyen de le résoudre? Est-ce une
limitation de bash, de xargs ou de perl? Merci d'avance.



Une solution serait d'obtenir cette lsite de fichiers dans ton script Perl
avec glob() par exemple :

$ perl -e '$pattern=shift||exit 1; @list = glob($pattern); print
join(":",@list), "n";' *.xml

Ne pas oublier d'echapper ton pattern '*.xml' que tu passe en parametre
pour qu'il ne soit pas interpreté par le shell.

On peut aussi le faire avec un readdir()

Avatar
lerouzic
Merci pour vos réponses rapides.

Pour information, xargs est limité par la taille des "paquets"
d'arguments (c'est à dire qu'on ne peut pas l'augmenter indéfiniment,
et que la valeur par défaut est proche du maximum d'ailleurs). Je me
suis donc rabattu vers une solution interne au script.

Comme alternative au passage des arguments sur l'entrée standard, il y
avait certainement le passage par un fichier temporaire:

find . -name "*.xml" > my_files.tmp
./my_script my_files.tmp

avec une lecture ligne à ligne de my_files.tmp

Passer le pattern en argument et utiliser glob() m'a semblé le plus
approprié. Pour l'instant, ça marche, et avec un peu de chance, la
prochaine limite est la mémoire du système, dans ce cas, j'ai de la
marge.

Encore merci à tous.

Arnaud.
Avatar
Patrice Auffret
On 14 Sep 2004 07:54:33 -0700
(Arnaud) wrote:

Bonjour à tous,

Je suis confronté à un problème qui me plonge dans un abîme de
perplexité. Voilà, j'essaye de passer un grand nombre d'arguments à un
script perl (ces arguments sont des noms de fichier), sous bash (Linux
Debian). J'avais commencé par un petit

./mon_script *.xml
[..]



use File::Find;

sub processFile {
print "processing: $File::Find::namen";
}

find(&processFile, "~/directory");