Ich habe den folgenden Befehl ausprobiert, nachdem ich dieses Video über Pipe Shenanigans gesehen habe.
man -k . | dmenu -l 20 | awk '{print $1}' | xargs -r man -Tpdf | zathura -
Grundsätzlich wird eine Liste von Manpages in das Menü gedruckt, damit der Benutzer eine davon auswählen kann. Anschließend wird xargs zum Ausführen man -Tpdf %
(Drucken, um ein PDF des Manpage-Git aus der Eingabe von xargs zu stdouten) verwendet und das PDF an einen PDF-Reader (zathura) übergeben ).
Das Problem ist, dass (wie Sie im Video sehen können) der PDF-Reader startet, noch bevor ich eine Manpage im Menü auswähle. Und wenn ich auf Esc klicke und keine auswähle, ist der PDF-Reader immer noch geöffnet und zeigt überhaupt kein Dokument an.
Wie kann ich den PDF-Reader (und jeden anderen Befehl in einer Pipe-Kette) so ausführen, dass er nur ausgeführt wird, wenn seine Eingabe das Dateiende erreicht oder wenn er überhaupt eine Eingabe empfängt? Oder wie kann ich alternativ eine Rohrkette zum Stoppen bringen, nachdem einer der verketteten Befehle einen Exit-Status ungleich Null zurückgegeben hat (sodass die folgenden Befehle nicht ausgeführt werden, wenn dmenu einen Fehler zurückgibt, wenn keine Option ausgewählt wurde)?
quelle
pipefail
in Kusalandandas Antwort erwähnten Bash- Option verwendet wird.Antworten:
Es gibt
ifne
(in Debian ist es immoreutils
Paket):In deinem Fall:
quelle
moreutils
) sollten im ursprünglichen Unix enthalten sein und von posix angegeben werden ... Es ist ein so grundlegendes und Unix-ifne
täuscht ein bisschen. Unix hat keine "Pipe Peek" -Operation,ifne
muss also mindestens ein Byte lesen, bevor der abhängige Befehl ausgeführt wird. Das heißt, es kann nicht nur den Test ausführen und den Befehl ausführen , sondern muss eine andere Pipe erstellen, einen anderen Prozess verzweigen, um den abhängigen Befehl auszuführen, und den gesamten Stream von der stdin-Pipe in die Downstream-Pipe kopieren. Wenn der Fall "Eingabe leer" nicht häufig vorkommt,ifne
kann er im Durchschnitt leicht mehr Ressourcen kosten, als er spart.PDF-Dateien sollen durchsuchbar sein; Jeder PDF-Betrachter muss zuerst auf den Trailer schauen und von dort zu den Offsets aus der XRef-Tabelle springen.
Da Pipes nicht durchsuchbar sind,
zathura
wird ein Verschleierungstrick verwendet, bei dem alle Eingaben in eine temporäre Datei kopiert werden und diese temporäre Datei dann wie gewohnt verwendet wird. Diese Art von "cleverem" Trick weckt falsche Hoffnungen und lässt vermuten, dass PDF-Dateien streambar sind.Aber egal,
zathura
wirklich tut Warten auf die EOF bevor das Dokument angezeigt wird , müssen Sie nichts tun , dafür zu hapen:Das Problem ist, dass
zathura
es keine Option gibt, das Fenster nur zu öffnen, wenn die Datei in Ordnung ist, und mit einem Fehler zu beenden, wenn dies nicht der Fall ist - es bleibt einfach dort, als ob alles in Ordnung ist:Selbst wenn Sie die Ausgabe selbst in eine temporäre Datei umleiten und nur ausführen,
zathura
wenn alles in Ordnung war, gibt es keine Garantie dafür, dass dem Benutzer kein schwarzes Fenster angezeigt wird, wennzathura
ihm die Ausgabe aus dem einen oder anderen Grund nicht gefällt .Übrigens,
zeigt eine Manpage in einem X11-Fenster mit an
gxditview
, auch wenn es direkt aus der '70 aussieht ;-)Und natürlich können Sie immer Folgendes verwenden:
Neben vielen anderen Verbesserungen können Sie bei der Suche und der richtigen Textauswahl reguläre Ausdrücke verwenden.
quelle
Alle Befehle in einer Pipeline werden fast gleichzeitig gestartet. Es ist nur die E / A über der Pipe, die sie synchronisiert. Außerdem kann eine Pipe nur so viele Informationen enthalten, wie der Puffer der Pipe zulässt.
Sie können daher nicht vermeiden, eine Stufe einer Pipeline auszuführen, weil
Schreiben Sie stattdessen die Ausgabe in eine Datei, während die Pipeline beendet wird. Verwenden Sie dann diese Datei.
Beispiel (als Funktion mit einem Argument):
Dies würde das
zathura
Programm außerdem nicht ausführen , wenn die Pipeline fehlschlägt (derxargs
Teil ist ungleich Null zurückgegeben) oder die generierte Datei leer ist.In der
bash
Shell möchten Sie möglicherweise auch diepipefail
Shell-Option festlegenset -o pipefail
, damit die Pipeline den Exit-Status des ersten fehlgeschlagenen Befehls in der Pipeline zurückgibt. Und Sie möchten dietmpfile
Variable machenlocal
:Dadurch wird die
pipefail
Option für die Dauer der Funktion festgelegt, sofern diese noch nicht festgelegt wurde, und bei Bedarf deaktiviert. Der-s
Test in der Ausgabedatei wird entfernt.quelle
rm -f
? Denken Sie an Fälle, in denen die Pipe die Berechtigungen der tmpfile ändert?rm -f
würde nicht ausfallen, wenn die Datei bereits entfernt wurde (möglicherweise vonzathura
, ich weiß nicht).pipefail
Option funktioniert wie erwartet (und auch in zsh, das dieselbe Option hat).