Wie kann ich stdout weiterleiten, während ich es auf dem Bildschirm halte? (und nicht zu einer Ausgabedatei)

233

Ich möchte die Standardausgabe eines Programms weiterleiten, während ich es auf dem Bildschirm halte.

Mit einem einfachen Beispiel ( echohier nur zur Veranschaulichung):

$ echo 'ee' | foo
ee <- die Ausgabe, die ich sehen möchte

Ich weiß, dass tee stdout in eine Datei kopieren kann, aber das ist nicht das, was ich will.
$ echo 'ee' | tee output.txt | foo

Ich habe es versucht,
$ echo 'ee' | tee /dev/stdout | fooaber es funktioniert nicht, da die Tee-Ausgabe an weitergeleitet /dev/stdoutwirdfoo

Gentooboontoo
quelle
6
Beachten Sie jedoch, dass dies echo 'ee' | tee /dev/stderrfunktioniert. Wenn also stderr auch Ihre Anforderung "auf dem Bildschirm" erfüllt, reicht dies aus.
nh2

Antworten:

343

Hier ist eine Lösung, die auf jeder Unix / Linux-Implementierung funktioniert, vorausgesetzt, sie muss dem POSIXStandard folgen . Es funktioniert auch in einigen Nicht-Unix-Umgebungen cygwin.

echo 'ee' | tee /dev/tty | foo

Referenz: Die Open Group Base-Spezifikationen Ausgabe 7 IEEE Std 1003.1, Ausgabe 2013, §10.1 :

/ dev / tty

Gegebenenfalls mit der Prozessgruppe dieses Prozesses verknüpft. Dies ist nützlich für Programme oder Shell-Prozeduren, die sicher sein möchten, dass Nachrichten an das Terminal geschrieben oder Daten vom Terminal gelesen werden, unabhängig davon, wie die Ausgabe umgeleitet wurde. Es kann auch für Anwendungen verwendet werden, die den Namen einer Datei für die Ausgabe benötigen, wenn eine typisierte Ausgabe gewünscht wird und es mühsam ist, herauszufinden, welches Terminal derzeit verwendet wird. In jedem Prozess ein Synonym für das steuernde Terminal

Es wurde berichtet, dass einige Umgebungen wie Google Colab nicht implementiert werden, /dev/ttywährend der ttyBefehl weiterhin ein verwendbares Gerät zurückgibt. Hier ist eine Problemumgehung:

tty=$(tty)
echo 'ee' | tee $tty | foo

oder mit einer alten Bourne-Muschel:

tty=`tty`
echo 'ee' | tee $tty | foo
jlliagre
quelle
5
@static_rtti Warum ignorierst du Jahr für Jahr meine Antworten auf deinen Kommentar?
Jlliagre
1
@PaulBissex /dev/ttyist ein obligatorisches Unix-Gerät. Laufen Sie in einem BSD-Gefängnis?
Jlliagre
1
@PaulBissex Das ist entweder eine Implementierung oder ein Konfigurationsfehler. Ist / dev montiert? Was zeigt "ls -l / dev / tty / dev / tty * / dev"? Siehe lists.freebsd.org/pipermail/freebsd-bugs/2012-November/… forums.freebsd.org/threads/…
jlliagre
1
Und Sie können teewie folgt kaskadieren : cat some.log | tee /dev/tty | tee -a other.log | grep -i 'foo' >> foo.log1) alles an die Konsole senden, 2) alles an eine andere Datei anhängen, 3) die fooZeilen an eine andere Datei senden.
Jesse Chisholm
1
Google Colab hat nicht /dev/tty, aber die Ausgabe von ttyist verwendbar.
Tom Hale
69

Eine andere Sache zu versuchen ist:

echo 'ee' | tee >(foo)

Das >(foo)ist eine Prozesssubstitution .

bmk
quelle
1
Was ist, wenn ich die Ausgabe von foo an eine andere Leiste weiterleiten möchte?
Jack Tang
3
@JackTang - Ich denke, dass jede weitere Weiterleitung der Ausgabe von fooTeil der Prozessersetzung sein muss. Hier ist ein Beispiel:echo 'ee' | tee file.txt >(wc -c | tr -d ' ')
Nick Chammas
1
Dies war die Lösung für mich auf FreeBSD (no / dev / tty)
Paul Bissex
9
@ Nick Chammas, Um eine normale Pipeline aufrechtzuerhalten, können Sie die Ausgänge von tee tauschen : echo 'ee' | tee >(cat) | foo | bar.
Vaelus
18

Der Zugriff auf "/ dev / stdout" wird auf einigen Systemen verweigert, der Zugriff auf das Benutzerterminal wird jedoch durch "/ dev / tty" gewährt. Unter Verwendung von "wc" für "foo" funktionieren die obigen Beispiele (unter Linux, OSX usw.) wie folgt:

% echo 'Hi' | tee /dev/tty | wc Hi 1 1 3

Um eine Anzahl am Ende einer Liste übereinstimmender Dateien hinzuzufügen, verwende ich Folgendes:
% ls [A-J]* | tee /dev/tty | wc -l

Um zu vermeiden, dass ich mich an all das erinnern muss, definiere ich Aliase:
% alias t tee /dev/tty
% alias wcl wc -l

damit ich einfach sagen kann:
% ls [A-J]* | t | wcl


POSTSCRIPT: Für die jüngere Gruppe, die bei der Aussprache als "Titty" kitzeln könnte, könnte ich hinzufügen, dass "tty" einst die gebräuchliche Abkürzung für ein "Teletyp" -Terminal war, das eine Rolle gelbes Papier verwendete und so oft runde Tasten hatte stecken.

user51527
quelle
17

Versuchen:

$ echo 'ee' | tee /dev/stderr | foo

Wenn die Verwendung von stderr natürlich eine Option ist.

Jan.
quelle
8

Zuerst müssen Sie das Terminal herausfinden, das Ihrem Bildschirm zugeordnet ist (oder auf welchem ​​Bildschirm die Ausgabe angezeigt werden soll):

tty

dann können Sie die Ausgabe an dieses Terminal senden und die andere Kopie durch Ihr foo-Programm leiten:

echo ee | tee /dev/pty/2 | foo
Michael Martinez
quelle
1
oneliner: t = $ (tty) echo ee | Tee $ t | foo | Bar
Jack Tang
5
@ JackTang Das ist zwar besser, aber tnutzlos. Sie können verwenden, echo ee | tee $(tty) | fooaber es hat immer noch einen nutzlosen Befehl ( tty), da die Tatsache /dev/ttynur funktioniert.
Jlliagre