Y a-t-il une sorte de limite de caractères imposée dans bash (ou d'autres shells) pendant combien de temps une entrée peut durer? Si oui, quelle est cette limite de caractères?
Ie Est-il possible d'écrire une commande en bash qui est trop longue pour que la ligne de commande s'exécute? S'il n'y a pas de limite requise, y a-t-il une limite suggérée?
bash
shell
unix
command-line-arguments
Derek Halden
la source
la source
Réponses:
La limite de longueur d'une ligne de commande n'est pas imposée par le shell, mais par le système d'exploitation. Cette limite est généralement de l'ordre de cent kilo-octets. POSIX indique cette limite
ARG_MAX
et sur les systèmes conformes POSIX, vous pouvez l'interroger avec$ getconf ARG_MAX # Get argument limit in bytes
Par exemple, sur Cygwin, il s'agit de 32000, et sur les différents BSD et systèmes Linux que j'utilise, il est compris entre 131072 et 2621440.
Si vous devez traiter une liste de fichiers dépassant cette limite, vous voudrez peut-être consulter l'
xargs
utilitaire, qui appelle un programme à plusieurs reprises avec un sous-ensemble d'arguments ne dépassant pasARG_MAX
.Pour répondre à votre question spécifique, oui, il est possible d'essayer d'exécuter une commande avec une liste d'arguments trop longue. Le shell fera une erreur avec un message le long de "liste d'arguments trop longue".
Notez que l' entrée d'un programme (comme lu sur stdin ou tout autre descripteur de fichier) n'est pas limitée (uniquement par les ressources de programme disponibles). Donc, si votre script shell lit une chaîne dans une variable, vous n'êtes pas limité par
ARG_MAX
. La restriction ne s'applique pas non plus aux shell-builtins.la source
cmd <<< "$LONG_VAR"
et que la valeur LONG_VAR dépassait la limite, cela ferait-il exploser ma commande?LONG_VAR
est transmis sur stdin - et cela se fait entièrement dans le shell; il n'est pas étendu comme argument àcmd
, donc la limite ARG_MAX pour fork () / exec () n'entre pas en jeu. Il est facile d'essayer par vous-même: créez une variable dont le contenu dépasse ARG_MAX et exécutez votre commande.blah="$(cat /home/schwager/Music/Recordings/20090420\ 131623.m4a)"; cat <<< $blah >/dev/null
. Ne notez aucune erreur.xargs
sur les limites macOS 10.12.6 combien il tente de mettre en unexec()
àARG_MAX - 4096
. Ainsi, l'utilisation de scriptsxargs
peut fonctionner, jusqu'au jour où quelqu'un met trop de choses dans l'environnement. Courir dans ce maintenant (contourner ce problème avec :)xargs -s ???
.Ok, les habitants. J'ai donc accepté les limites de longueur de la ligne de commande comme évangile depuis un certain temps. Alors, que faire de ses hypothèses? Naturellement, vérifiez-les.
J'ai une machine Fedora 22 à ma disposition (c'est-à-dire Linux avec bash4). J'ai créé un répertoire contenant 500 000 inodes (fichiers) de 18 caractères chacun. La longueur de la ligne de commande est de 9 500 000 caractères. Créé ainsi:
seq 1 500000 | while read digit; do touch $(printf "abigfilename%06d\n" $digit); done
Et nous notons:
Notez cependant que je peux faire ceci:
$ echo * > /dev/null
Mais cela échoue:
$ /bin/echo * > /dev/null bash: /bin/echo: Argument list too long
Je peux exécuter une boucle for:
$ for f in *; do :; done
qui est un autre shell intégré.
Lecture attentive de la documentation des
ARG_MAX
états, longueur maximum d'argument des fonctions exec . Cela signifie: sans appelexec
, il n'y a pas deARG_MAX
limitation. Cela expliquerait donc pourquoi les fonctions internes du shell ne sont pas limitées parARG_MAX
.Et en effet, je peux
ls
mon répertoire si ma liste d'arguments contient 109948 fichiers, soit environ 2 089 000 caractères (donner ou prendre). Une fois que j'ajoute un autre fichier de nom de fichier à 18 caractères, j'obtiens une erreur de liste d'arguments trop longue . CelaARG_MAX
fonctionne donc comme annoncé: l'exécution échoue avec plus deARG_MAX
caractères sur la liste d'arguments - y compris, il faut le noter, les données d'environnement.la source
for f in *; do echo $f; done
ne bifurquera pas du tout (tous intégrés). Donc je ne sais pas qu'un combo find-xargs sera plus rapide; il n'a pas été testé. En effet, je ne sais pas quel est le problème de l'OP. Peutfind /path/to/directory
- être ne lui sera - t - il pas utile car il renverra le chemin du fichier. Peut-être qu'il aime la simplicité d'unefor f in *
boucle. Quoi qu'il en soit, la conversation porte sur la limite d'entrée de ligne et non sur l'efficacité. Restons donc sur le sujet, qui concerne la longueur de la ligne de commande.Il y a une limite de tampon de quelque chose comme 1024. La lecture se bloquera simplement au milieu de la pâte ou de l'entrée. Pour résoudre ce problème, utilisez l'option -e.
http://linuxcommand.org/lc3_man_pages/readh.html
-e utilise Readline pour obtenir la ligne dans un shell interactif
Changez votre lecture en read -e et le blocage d'entrée de ligne ennuyeux disparaît.
la source
read
: "Ie est-il possible d'écrire une commande dans bash qui est trop longue pour que la ligne de commande s'exécute?"bash --noediting
-à- dire , et à la nouvelle invite, essayez d'exécuter la commandeecho somereallylongword
, où somereallylongword est plus long que 4090 caractères. Essayé sur Ubuntu 18.04, le mot a été tronqué, donc évidemment cela a quelque chose à voir avec Readline non activé.