2010-09-16 13:40:08 +0000 2010-09-16 13:40:08 +0000
88
88

Wie kann ich die Ausgabe eines Befehls an andere Befehle weiterleiten?

Beispiel:

ls | echo druckt nichts (eigentlich eine Leerzeile). Ich würde erwarten, dass es eine Liste von Dateien ausgibt.

ls | grep 'foo' hingegen funktioniert wie erwartet (druckt Dateien mit ‘foo’ im Namen).

Was ich in diesen Situationen mache, ist so etwas wie: ls | while read OUT; do echo $OUT; done, aber das ist ziemlich umständlich.

Warum funktioniert das Piping bei einigen Befehlen, bei anderen aber nicht ? Wie kann ich dieses Problem umgehen ?

Antworten (4)

123
123
123
2010-09-16 14:16:59 +0000

Es wird zwischen Befehlszeilenargumenten und Standardeingabe unterschieden. Eine Pipe verbindet die Standardausgabe eines Prozesses mit der Standardeingabe eines anderen. Also

ls | echo

Verbindet die Standardausgabe von ls mit der Standardeingabe von echo. Gut, oder? Nun, echo ignoriert die Standardeingabe und gibt seine Kommandozeilenargumente - die in diesem Fall keine sind - in sein eigenes stdout aus. Die Ausgabe: gar nichts.

In diesem Fall gibt es ein paar Lösungen. Eine ist, einen Befehl zu verwenden, der stdin liest und nach stdout ausgibt, wie z. B. cat.

ls | cat

Wird “funktionieren”, je nachdem, was Ihre Definition von Arbeit ist.

Aber was ist mit dem allgemeinen Fall. Was Sie wirklich wollen, ist, stdout eines Befehls in Kommandozeilen-Args eines anderen zu konvertieren. Wie andere schon gesagt haben, ist xargs in diesem Fall das kanonische Hilfswerkzeug, das die Kommandozeilen-Args für einen Befehl aus dessen stdin liest und die auszuführenden Befehle konstruiert.

ls | xargs echo

Sie könnten dies auch etwas umwandeln, indem Sie den Ersetzungsbefehl $()

echo $(ls)

verwenden, der auch das tun würde, was Sie wollen.

Diese beiden Werkzeuge sind ziemlich zentral für das Shell-Scripting, Sie sollten beide lernen.

Der Vollständigkeit halber: Wie Sie in der Frage andeuten, ist die andere grundlegende Möglichkeit, stdin in Kommandozeilen-Args zu konvertieren, der in der Shell eingebaute Befehl read. Er konvertiert “words” (Wörter, wie sie durch die Variable IFS definiert sind) in eine temp-Variable, die Sie in beliebigen Befehlsläufen verwenden können.

19
19
19
2010-09-16 13:54:37 +0000

ls | echo druckt nur eine Leerzeile, weil echo keine Eingabe liest; der letzte Befehl der Pipeline ist eigentlich echo, der nichts als eine Leerzeile druckt.

Generell:

a | b

sorgt dafür, dass die Ausgabe von a die Eingabe von b wird. Ich empfehle Ihnen, den Abschnitt Pipelines von man bash zu lesen.


Wenn Sie ls und echo wirklich zusammen benutzen wollen, hier ein paar (ziemlich nutzlose) Beispiele:

ls | xargs -L 1 echo
echo `ls`
for i in `ls` ; do echo $i ; done
13
13
13
2010-09-16 14:03:04 +0000

Wenn Sie echo den Befehl ls versuchen wollen:

ls | xargs echo

Dies wird echo mit der Ausgabe von ls aufrufen.

3
3
3
2011-11-09 09:48:27 +0000

Warum nicht einfach verwenden:

echo `ls`

Oder viel sicherer:

echo "`ls -lrt`"