Es gibt einige Befehle, die Eingaben filtern oder bearbeiten und sie dann als Ausgabe weitergeben, denke ich normalerweise stdout
- aber einige Befehle nehmen einfach das stdin
und tun, was sie damit tun, und geben nichts aus.
Ich kenne mich am besten mit OS X aus und so gibt es zwei, die mir sofort einfallen pbcopy
und pbpaste
- die Mittel zum Zugriff auf die Systemzwischenablage.
Jedenfalls weiß ich, dass ich stdout
den tee
Befehl verwenden kann , wenn ich stdout nehmen und die Ausgabe spucken möchte, um auf beide und eine Datei zuzugreifen. Und ich weiß ein wenig darüber xargs
, aber ich glaube nicht, dass ich danach suche.
Ich möchte wissen, wie ich stdout
zwischen zwei (oder mehr) Befehlen aufteilen kann . Zum Beispiel:
cat file.txt | stdout-split -c1 pbcopy -c2 grep -i errors
Es gibt wahrscheinlich ein besseres Beispiel als dieses, aber ich bin wirklich daran interessiert zu wissen, wie ich stdout an einen Befehl senden kann, der es nicht weiterleitet, und dabei stdout
nicht "stumm" geschaltet wird - ich frage nicht, wie cat
und grep
Teil davon und kopieren Sie es in die Zwischenablage - die spezifischen Befehle sind nicht so wichtig.
Außerdem - ich frage nicht, wie ich das an eine Datei senden soll, und stdout
- dies ist möglicherweise eine "doppelte" Frage (sorry), aber ich habe einige gesucht und konnte nur ähnliche finden, die gefragt haben, wie man zwischen stdout und einer Datei aufteilt - und die Antworten auf diese Fragen schienen zu sein tee
, von denen ich nicht glaube, dass sie für mich funktionieren.
Zum Schluss fragen Sie sich vielleicht, warum Sie pbcopy nicht zum letzten Element in der Pipe-Kette machen sollten. und meine Antwort ist 1) was ist, wenn ich es verwenden und trotzdem die Ausgabe in der Konsole sehen möchte? 2) Was ist, wenn ich zwei Befehle verwenden möchte, die nicht ausgegeben werden, stdout
nachdem sie die Eingabe verarbeitet haben?
Oh, und noch etwas - mir ist klar, dass ich tee
eine Named Pipe ( mkfifo
) verwenden kann, aber ich hatte gehofft, dass dies ohne vorherige Einrichtung inline erfolgen kann :)
Antworten:
Sie können dafür die
tee
Substitution verwenden und verarbeiten:Dadurch wird die gesamte Ausgabe von
cat file.txt
anpbcopy
gesendet, und Sie erhalten nur das Ergebnis vongrep
auf Ihrer Konsole.Sie können mehrere Prozesse in das
tee
Teil einfügen:quelle
pbcopy
, aber generell erwähnenswert: Unabhängig von den Prozesssubstitutionsausgaben wird diese auch vom nächsten Rohrsegment nach der ursprünglichen Eingabe angezeigt. Beispiel:seq 3 | tee >(cat -n) | cat -e
(cat -n
nummeriert die Eingabezeilen,cat -e
markiert die neuen Zeilen mit$
; Sie werden sehen, dass diescat -e
sowohl auf die ursprüngliche Eingabe (zuerst) als auch auf die Ausgabe von angewendet wirdcat -n
). Die Ausgabe mehrerer Prozessersetzungen erfolgt in nicht deterministischer Reihenfolge.>(
funktioniert nur inbash
. Wenn Sie das zum Beispiel mit versuchen,sh
funktioniert es nicht. Es ist wichtig, dies zu bemerken.dash
, die sich wiesh
Ubuntu verhalten, unterstützen es nicht und selbst Bash deaktiviert die Funktion, wenn sie aufgerufen wirdsh
oder wenn sieset -o posix
in Kraft ist. Allerdings ist es nicht nur Bash , die Prozess Ersetzungen unterstützt:ksh
undzsh
unterstützen sie auch (nicht sicher über andere).bash
undksh
-zsh
scheinbar Ausgabe von Ausgangsprozess Ersetzungen durch die Pipeline nicht (wohl schicken, das ist vorzuziehen , weil sie nicht verschmutzen , was auf das nächste Pipeline - Segment gesendet wird - obwohl es wird noch gedruckt ). In allen genannten Shells ist es jedoch im Allgemeinen keine gute Idee, eine einzelne Pipeline zu haben, in der die reguläre Standardausgabe und die Ausgabe von Prozessersetzungen gemischt werden Ausgabedatensätze.Sie können mehrere Dateinamen angeben
tee
, und zusätzlich kann die Standardausgabe in einen Befehl umgeleitet werden. Um die Ausgabe an mehrere Befehle zu senden, müssen Sie mehrere Pipes erstellen und diese jeweils als eine Ausgabe von angebentee
. Hierfür gibt es verschiedene Möglichkeiten.Prozessersetzung
Wenn Ihre Shell ksh93, bash oder zsh ist, können Sie die Prozessersetzung verwenden. Auf diese Weise können Sie eine Pipe an einen Befehl übergeben, der einen Dateinamen erwartet. Die Shell erstellt die Pipe und übergibt
/dev/fd/3
dem Befehl einen Dateinamen . Die Nummer ist der Dateideskriptor , mit dem die Pipe verbunden ist. Einige Unix-Varianten unterstützen dies nicht/dev/fd
. Auf diesen wird stattdessen eine Named Pipe verwendet (siehe unten).Dateideskriptoren
In jeder POSIX-Shell können Sie mehrere Dateideskriptoren explizit verwenden. Dies setzt eine unterstützte Unix-Variante voraus
/dev/fd
, da bis auf eine alle Ausgabentee
von namentlich angegeben werden müssen.Named Pipes
Die einfachste und portabelste Methode ist die Verwendung von Named Pipes . Der Nachteil ist, dass Sie ein beschreibbares Verzeichnis finden, die Pipes erstellen und anschließend bereinigen müssen.
quelle
tee "$tmp_dir/f1" "$tmp_dir/f2" | command3
sollte doch seincommand3 | tee "$tmp_dir/f1" "$tmp_dir/f2"
, wie du willst, stdout ofcommand3
piped totee
, no? Ich habe Ihre Version unter getestetdash
undtee
blockiert das Warten auf Eingaben auf unbestimmte Zeit, aber das Umschalten der Reihenfolge ergab das erwartete Ergebnis.command
,command2
undcommand3
.<command> | bash -c 'tee >(command1) >(command2) | command3'
. Es hat in meinem Fall geholfen.Spielen Sie einfach mit der Prozessersetzung.
grep
sind zwei Binärdateien, deren Ausgabemycommand_exec
mit der prozessspezifischen Eingabe übereinstimmt .quelle
Wenn Sie verwenden
zsh
, können Sie die Leistungsfähigkeit derMULTIOS
Funktion nutzen, dh dentee
Befehl vollständig loswerden :schreibt nur die Ausgabe von
uname
zwei verschiedenen Dateien:file1
undfile2
, was ist gleichbedeutend mituname | tee file1 >file2
Ebenso Umleitung von Standardeingaben
entspricht
cat file1 file2 | wc -l
(bitte beachten Sie, dass dies nicht dasselbe ist, dawc -l file1 file2
die spätere Anzahl der Zeilen in jeder Datei separat gezählt wird).Natürlich können Sie
MULTIOS
die Ausgabe auch verwenden , um sie nicht in Dateien, sondern in andere Prozesse umzuleiten, indem Sie die Prozessersetzung verwenden, z.quelle
MULTIOS
ist eine Option , die standardmäßig aktiviert ist (und mit deaktiviert werden kannunsetopt MULTIOS
).Für eine relativ kleine Ausgabe, die durch einen Befehl erzeugt wird, können wir die Ausgabe in eine temporäre Datei umleiten und diese temporäre Datei in einer Schleife an Befehle senden. Dies kann nützlich sein, wenn die Reihenfolge der ausgeführten Befehle eine Rolle spielt.
Das folgende Skript könnte dies beispielsweise tun:
Testlauf auf Ubuntu 16.04 mit
/bin/sh
alsdash
Shell:quelle
Erfassen Sie den Befehl
STDOUT
in einer Variablen und verwenden Sie ihn so oft Sie möchten:Wenn Sie erfassen müssen
STDERR
auch dann verwenden ,2>&1
am Ende des Befehls, etwa so:quelle
Dies kann von Nutzen sein: http://www.spinellis.gr/sw/dgsh/ (Shell für gerichtete Grafiken) Scheint wie ein Bash-Ersatz, der eine einfachere Syntax für "Multipipe" -Befehle unterstützt.
quelle
Hier ist eine schnelle und schmutzige Teillösung, die mit jeder Shell einschließlich kompatibel ist
busybox
.Das engere Problem, das es löst, ist: Drucken Sie das komplette
stdout
Dokument auf einer Konsole und filtern Sie es auf einer anderen, ohne temporäre Dateien oder Named Pipes.tty
. Nehmen wir an/dev/pty/2
.the_program | tee /dev/pty/2 | grep ImportantLog:
Sie erhalten ein vollständiges und ein gefiltertes Protokoll.
quelle