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
dir2
auszulagern 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 :
cmd2
ist ein Unterprozess voncmd1
.- die stdin von
cmd2
ist "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