Vous confondez arguments et entrée standard. Transférer des données à un programme n'équivaut pas à lui donner des arguments de ligne de commande.
Dans votre premier cas, vous ne transmettez aucun argument à votre script, vous ne lui fournissez que des données via son flux d'entrée standard. Donc $1
est désactivé pendant toute la durée du script.
La première invocation de more
n'a donc pas de paramètre, et pagine l'entrée standard. Cela affiche ce que vous avez inséré (dir1
, sous forme de texte). Le echo
suivant n'imprime qu'une nouvelle ligne car il n'obtient rien à imprimer, et le dernier more
n'a plus rien à imprimer non plus - l'entrée standard a été "vidée" par la première.
Dans le second cas, vous passez un argument. Alors $1
a la valeur dir2
dans le scénario. La même chose se produit, sauf que le premier more
les deux :
- pages via les deux entrées standard
- tente de paginer le fichier
dir2
et les erreurs étant donné qu'il s'agit d'un répertoire
L'écho fait ce qui est attendu étant donné que $1
contient dir2
, et le dernier more
uniquement les erreurs sur dir2
- il n'a rien à lire à partir de l'entrée standard.
La différence est dans "Arguments " VS " Saisie standard ".
Lorsque vous exécutez echo dir1 | bash script.sh
, le $1
argumentation dans votre script.sh
est toujours vide car aucun argument ne lui est donné (essayez d'ajouter un set -x
au début et vous le verrez dans la sortie de débogage). Le dir1
dont l'écho provient de l'entrée standard comme le more
la commande lit stdin si aucun argument n'est donné (rappelez-vous $1
est vide).
Comment cmd1 | cmd2
fonctionne
Lors de l'utilisation d'un tuyau :
cmd2
est un sous-processus decmd1
.- le stdin de
cmd2
est "branché" sur la sortie standard decmd1
.
Comme linux stdio lib offrait un flux mis en mémoire tampon via le descripteur de fichier, le contenu stdin sera consommé (c'est-à-dire lu une seule fois) uniquement lorsque stdin sera ouvert .
Pas à pas cmd1 | cmd2
flux de travail
Exemple de commande :
echo dir1 | (echo "a" ; read stdinvalue; echo "$stdinvalue")
echo dir1 |
:écrire "dir1\n
" sur stdout de la première commande qui n'est pas renvoyée en écho mais mise en mémoire tampon via stdio et disponible pour sous-traiter via stdin.echo "a"
:écrire "a\n
" sur stdout ; ne lit pas stdin ! donc le "dir1\n
" la chaîne est toujours disponibleread stdinvalue
:lit stdin jusqu'à EOL (ou EOF) et stocke la chaîne dans une variable bashecho "$stdinvalue"
:écrit la valeur de la variable stdinvalue dans stdout