Was macht das Linux-Pipe-Symbol "|"? [Duplikat]

23

Hier ist ein Befehl, der Dateien in einem Ordner in umgekehrter Reihenfolge sortiert

ls | sort -r

Was bewirkt das |Symbol in diesem Befehl?

Was ich hier wirklich suche, ist eine gute (leicht verständliche) Erklärung der Pipes für Linux-Anfänger. Ich sehe hier im Superuser andere Fragen zu Pipes, aber nichts, was eine Antwort hervorruft, die in einfachen Worten erklärt, was sie tun und wie sie sich von der Umleitung unterscheiden (das Symbol >oder <).

ccalvert
quelle
7
Dies hat nichts mit Linux (einem Kernel) zu tun. Pipes sind im Allgemeinen ein Mittel zur Umleitung von Ein- und Ausgängen. In einer Shell wie bash ist dies nicht anders. Das Besondere an a |ist, dass es keinen Namen verwendet. Die Ausgabe des Befehls l-hand wird direkt an die Eingabe für den Befehl auf der rechten Seite der Pipe übergeben.
Andon M. Coleman
Eine Geschichtsstunde zu diesem Thema finden Sie unter linfo.org/pipe.html
Fredrik Pihl,
ls -1r(Beachten Sie das Argument Nr. 1) sollte zu einem ähnlichen Ergebnis führen wie ls | sort -r.
Ivan Chau
Ich erkläre es gerne so: Eine Pipe nimmt die Ausgabe eines Befehls und macht sie für einen folgenden Befehl verwendbar. Zum Beispiel können Sie tun cat /somefile | grep cool. Dies nimmt die Ausgabe von somefile und stellt sie für grep zur Verfügung, und grep druckt dann alle Zeilen, in denen das Wort cool enthalten ist.
JohnDoea

Antworten:

26

Das Folgende wird ein wenig vereinfacht, um neuen Benutzern zu helfen.

Zunächst müssen Sie das Konzept der Standardeingabe und der Standardausgabe verstehen.

In Linux und anderen UNIX-ähnlichen Betriebssystemen verfügt jeder Prozess über eine Standardeingabe ( stdin) und eine Standardausgabe ( stdout). Die übliche Situation ist, dass dies stdinIhre Tastatur und stdoutIhr Bildschirm oder Terminalfenster ist.

Wenn du also rennst ls, wirft es die Ausgabe auf stdout. Wenn Sie nichts anderes tun, wird der Bildschirm oder das Terminalfenster angezeigt.

Nun interagieren einige Linux-Befehle mit dem Benutzer und verwenden stdindies, wobei Ihr Texteditor einer dieser Befehle ist . Es liest aus stdin, um Ihre Tastatureingaben zu akzeptieren, Dinge zu tun und dann Dinge zu schreiben stdout.

Es gibt jedoch auch nicht interaktive oder "Filter" -Befehle, die NICHT interaktiv funktionieren, sondern eine Reihe von Daten benötigen. Diese Befehle nehmen alles stdin, was es gibt, tun etwas und werfen es dann zustdout

Schauen wir uns einen anderen Befehl mit dem Namen an du- steht für die Festplattennutzung. du /usrZum Beispiel wird stdouteine Liste aller Dateien in diesem Verzeichnis und ihrer Größe gedruckt (so wie bei jedem anderen Linux-Befehl):

# du /usr
2312    /usr/games
124     /usr/lib/tc
692     /usr/lib/rygel-1.0
400     /usr/lib/apt/methods
40      /usr/lib/apt/solvers
444     /usr/lib/apt
6772    /usr/lib/gnash

Wie Sie gleich erkennen können, ist es nicht sortiert und Sie möchten es wahrscheinlich in der Reihenfolge der Größe sortiert haben.

sortist einer dieser "Filter" -Befehle, die eine Menge Dinge entnehmen stdinund sortieren.

Also, wenn wir das tun:

# du /usr | sort -nr

wir bekommen das, was ein bisschen besser ist:

4213348 /usr
2070308 /usr/lib
1747764 /usr/share
583668  /usr/lib/vmware
501700  /usr/share/locale
366476  /usr/lib/x86_64-linux-gnu
318660  /usr/lib/libreoffice
295388  /usr/lib/vmware/modules
290376  /usr/lib/vmware/modules/binary
279056  /usr/lib/libreoffice/program
216980  /usr/share/icons

Und Sie können jetzt sehen, dass die "Pipe" den stdoutvon einem Befehl mit dem stdinvon einem anderen verbindet. Normalerweise werden Sie es in Situationen wie diesen verwenden, in denen Sie die Ausgabe eines Befehls filtern, sortieren oder anderweitig bearbeiten möchten. Sie können kaskadiert werden, wenn Sie die Ausgabe über mehrere Filterbefehle verarbeiten möchten.

Wenn Sie selbst tippen sort, wird weiterhin versucht, auszulesen stdin. Da stdines mit Ihrer Tastatur verbunden ist, wartet es darauf, dass Sie etwas eingeben und verarbeiten, bis Sie Strg-D drücken. Es wird Sie nicht dazu auffordern, da es nicht wirklich für die interaktive Verwendung gedacht ist.

Es ist möglich, dass ein Programm erkennt, ob stdines interaktiv ist oder nicht. Einige Programme verhalten sich daher möglicherweise anders, wenn Sie sie selbst oder am Ende einer Pipe ausgeben.

Außerdem führt das Weiterleiten eines Programms, das nur interaktiv funktioniert vi, zu einer schlechten Zeit.

Pipes unterscheiden sich von der Umleitung darin, dass die Daten von einem Befehl zum nächsten gemischt werden, ohne dass sie irgendwo gespeichert werden. Im obigen Beispiel wird dudie Ausgabe also nirgendwo gespeichert. Die meiste Zeit möchten Sie dies nicht mit Pipes tun, da der Grund für die Verwendung von Pipes darin besteht, die Ausgabe eines Befehls auf irgendeine Weise zu verarbeiten. Es gibt jedoch einen Befehl tee, mit dem Sie Ihren Kuchen haben und ihn auch essen können Kopieren Sie die empfangenen Daten stdinin stdouteine Datei Ihrer Wahl. Sie können dies wahrscheinlich auch bashmit einer arkanen Syntax tun, die Et-Zeichen und Klammern enthält, die ich nicht kenne.

LawrenceC
quelle
Beachten Sie, dass dies nicht nur für Linux oder POSIX gilt. Die meisten (alle?) Shells unter Windows tun dies auch. Und wahrscheinlich auch andere Betriebssysteme.
Bob
Ich kenne das Konzept von stdinund stdoutist unter Windows anders als unter Linux, obwohl es aus Sicht von Windows cmd.exeoder Powershell wahrscheinlich nicht sehr viel ist .
LawrenceC
Ich bin ziemlich neugierig, wie es anders ist - würde es Ihnen etwas ausmachen, es zu erklären? Vielleicht im Chat, wenn Kommentare kein guter Ort dafür sind.
Bob
1
Win32-Programme verfügen auf jeden Fall über eine Standardeingabe und -ausgabe. Beispielsweise können Sie die Standardeingabe, -ausgabe oder das Fehlerhandle Ihres Prozesses mit der Win32-Funktion abrufen GetStdHandle(). Es ist auch trivial, die Standard-Streams eines [untergeordneten] Prozesses mit .NET umzuleiten, von denen ich glaube, dass sie Win32-Funktionen zugeordnet sind (da bin ich mir nicht 100% sicher - ich bin kein Win32-Entwickler).
Bob
1
Ah, hier ist das Win32-Äquivalent, indem Sie die entsprechenden Parameter in der STARTUPINFOStruktur für festlegen CreateProcess().
Bob
27

Wenn Sie mit Ausgabe- und Eingabeumleitung vertraut sind, ist die Erklärung recht einfach.

Command1 | Command2

macht das selbe wie

Command1 > tempfile
Command2 < tempfile

aber ohne tempfile. Der Ausgang von Command1ist direkt mit dem Eingang von verbunden Command2und die Übertragung erfolgt im Speicher.

Daniel B
quelle
Ich könnte mich irren, aber ich denke, das tempfile existiert auch in der Pipe-Syntax. Es hat einfach keinen Namen.
Taemyr
3
Nein, tut es nicht. Es sind keine Dateisystemoperationen erforderlich, wenn die Ausgabe von einem Befehl an die Eingabe eines anderen Befehls weitergeleitet wird.
Daniel B
1
Unter DOS (und höchstwahrscheinlich unter Windows) wird von der Pipe eine temporäre Datei erstellt. Nicht * nix, aber nichts wert den Unterschied.
Jeremy J Starcher
Ich bin mir ziemlich sicher, dass das nicht stimmt. Process Monitor meldet keine CreateFileoder WriteFileruft an, um Ihren Anspruch zu stützen. / edit: Das ist natürlich für den Windows-Teil.
Daniel B
3

Wenn Sie wirklich wissen möchten, was Pipes tun und was zwischen> und | zu unterscheiden ist, wechseln Sie in ein Verzeichnis mit vielen Dateien und

von einem Terminal ls vs ls | more (oder unter Windows mit DIR und DIR | MORE)

Wenn Sie> more verwendet haben, wird eine Datei mit dem Namen 'more' erstellt, anstatt die Ausgabe von ls an den Befehl 'more' zu senden. Wenn also jemand mehr tun würde, wäre es wahrscheinlich ein Fehler, man würde nicht mehr tun, als Sie tun würden file1. More ist ein bekannter Befehl.

Das <like the> dient auch zum Verknüpfen eines Befehls und einer Datei anstelle eines Befehls mit einem Befehl. Aber während> die Ausgabe eines Befehls an eine Datei sendet, sendet <eine Datei als Eingabe für einen Befehl. Ich verwende selten <, da ich normalerweise cat file1 | verwende um die Ausgabe einer Datei an einen Befehl zu senden.

$ grep a <file1 abc

$ cat file1 | grep a abc

grep mit 2 Parametern hat die Form grep pattern file. grep mit einem Parameter ist grep pattern. Sie können die Datei auch senden, indem Sie den Inhalt der Datei an diese weiterleiten oder <verwenden. Wenn Sie <verwenden, schreiben Sie zuerst den Befehlsnamen und anschließend den Dateinamen. Bei Verwendung von | Um den Inhalt einer Datei weiterzuleiten, verwenden Sie cat file1 | Befehl.

Außerdem nehmen viele Befehle eine Datei als Eingabe, sodass grep eine Datei1 genau wie cat file1 | funktioniert grep a und grep a <file1.

Ich habe vor 15 Jahren Pipes (|) und> auf DOS gemacht.

Um zusammenzufassen, wie unterscheidet sich von <und> - Die Pipe befindet sich zwischen 2 Befehlen. Die <und> befinden sich zwischen einem Befehl und einer Datei. Das> wird in eine Datei ausgegeben. Das <wird aus einer Datei eingegeben.

barlop
quelle
3

Das Pipe-Zeichen ( |) verbindet die Ausgabe eines Programms mit der Eingabe eines anderen.

In diesem Beispiel wird echodas Wort gedruckt hellound wc -cdie Anzahl der Zeichen für die Eingabe bestimmt:

echo hello | wc -c
bbaassssiiee
quelle
Ich denke, Sie sollten sofort sagen, dass das Echo "Hallo \ n" ausgeben wird. Sie sagen dem OP nicht, dass er studieren soll, sondern jedem, der Ihre Antwort liest. Warum diese Zeitverschwendung multiplizieren?
Rodrigo
Danke für das Feedback, ich habe meine Antwort gekürzt.
bbaassssiiee
2

Um dies zu verstehen, probieren Sie es selbst aus:

sort -r

Jetzt hängst du mit einem Cursor und es tut nichts. Was passiert, wenn Sie Daten eingeben?

1
2
3
5
4

Immer noch nichts, richtig? Drücken Sie nun Strg + D

5
4
3
2
1

Das heißt, es nimmt Eingaben (was Sie eingegeben haben), macht etwas damit (sortiert) und gibt es als Ausgabe zurück. Der lsBefehl nimmt keine Eingaben entgegen, sondern generiert nur Ausgaben. Das Pipe-Symbol nimmt die Ausgabe von lsund gibt sie als Eingabe an den sortBefehl weiter.

>speist die Ausgabe nicht in ein Programm ein, sondern speichert sie als Datei. <Verwendet eine Datei als Eingabe.

jornane
quelle