Sie verwechseln Argumente und Standardeingabe. Das Weiterleiten von Daten an ein Programm ist nicht gleichbedeutend damit, ihm Befehlszeilenargumente zu geben.
In Ihrem ersten Fall übergeben Sie Ihrem Skript keine Argumente, sondern füttern es nur mit Daten über seinen Standardeingabestrom. Also $1 wird für die gesamte Dauer des Skripts nicht gesetzt.
Der erste Aufruf von more hat also keinen Parameter und blättert die Standardeingabe um. Dies zeigt an, was Sie dort eingegeben haben (dir1 , als Text). Die nachfolgende echo gibt nur eine neue Zeile aus, da nichts zu drucken ist, und die letzte more hat auch nichts mehr zu drucken - die Standardeingabe wurde von der ersten "ausgeschöpft".
Im zweiten Fall übergeben Sie ein Argument. Also $1 hat den Wert dir2 im Skript. Dasselbe passiert, außer dass der erste more beide:
- blättert durch beide Standardeingaben
- versucht, die Datei
dir2auszulagern und Fehler aus, da dies ein Verzeichnis ist
Das Echo tut, was erwartet wird, wenn $1 gegeben ist enthält dir2 , und die letzte more nur Fehler auf dir2 - es hat nichts von der Standardeingabe zu lesen.
Der Unterschied liegt in "Argumente " VS "Standardeingabe ".
Wenn Sie echo dir1 | bash script.sh ausführen , die $1 Argument in Ihrem script.sh ist immer leer, da ihm kein Argument gegeben wird (versuchen Sie, einen set -x hinzuzufügen am Anfang und Sie werden es in der Debug-Ausgabe sehen). Der dir1 was wiedergegeben wird, kommt von der Standardeingabe als more Befehl liest stdin, wenn kein Argument angegeben ist (denken Sie an $1 ist leer).
Wie cmd1 | cmd2 funktioniert
Bei Verwendung von Pipe :
cmd2ist ein Unterprozess voncmd1.- die stdin von
cmd2ist "eingesteckt" auf der Standardausgabe voncmd1.
Da Linux stdio lib einen gepufferten Stream über den Dateideskriptor anbot, wird der stdin-Inhalt verbraucht (d. h. nur einmal gelesen), nur wenn stdin geöffnet wird .
Schritt für Schritt cmd1 | cmd2 Arbeitsablauf
Beispielbefehl:
echo dir1 | (echo "a" ; read stdinvalue; echo "$stdinvalue")
echo dir1 |:schreibe "dir1\n" auf stdout des ersten Befehls, der nicht zurückgemeldet, sondern durch stdio gepuffert wird und für Unterprozesse über stdin verfügbar ist.echo "a":schreibe "a\n" auf stdout; liest stdin nicht ! also die "dir1\n"String ist noch verfügbarread stdinvalue:liest stdin bis EOL (oder EOF) und speichert den String in einer Bash-Variablenecho "$stdinvalue":stdinvalue-Variablenwert nach stdout schreiben