weniger Datei1 Datei2 | Katze - warum funktioniert es?

21

Wenn ich es verwende less file1 file2, werden beide Dateien im "less buffer viewer" angezeigt, aber less file1 file2 | catder Inhalt beider Dateien wird an stdout angehängt. Woher weiß weniger, ob es den "less buffer viewer" anzeigen oder eine Ausgabe an stdout für einen nächsten Befehl erzeugen soll? Welcher Mechanismus wird dazu verwendet?

tfh
quelle

Antworten:

30

lessdruckt text auf stdout. stdout geht

  • zu einem Terminal (/ dev / tty?) und öffnet den Standardpuffer-Viewer
  • durch eine Pipe, wenn sie mit | zu einem anderen Programm geleitet wird ( less text | cut -d: -f1)
  • in eine Datei umleiten mit> ( less text > tmp)

Es gibt eine C-Funktion namens "isa tty ", die prüft, ob die Ausgabe auf ein tty (weniger als 4,81, main.c, Zeile 112) geht. In diesem Fall wird der Puffer-Viewer verwendet, ansonsten verhält er sich wie folgt cat.

In Bash können Sie Test verwenden (siehe man test)

  • -t FD-Dateideskriptor FD wird auf einem Terminal geöffnet
  • -p DATEI existiert und ist eine Named Pipe

Beispiel:

[[ -t 1 ]] && \
    echo 'STDOUT is attached to TTY'

[[ -p /dev/stdout ]] && \
    echo 'STDOUT is attached to a pipe'

[[ ! -t 1 && ! -p /dev/stdout ]] && \
    echo 'STDOUT is attached to a redirection'
Michael D.
quelle
1
@tfh Wenn STDOUT nicht an eine Pipe oder eine Umleitung angehängt ist, wird STDOUT nicht an eine Pipe oder eine Umleitung angehängt. Schreiben Sie alle drei in ein Skript. Rufen Sie bash script.sh, bash script.sh | cat, bash script.sh > file, und sehen , was Ausgabe , die Sie erhalten.
HDV
1
stdoutkann nicht in eine Datei geschrieben werden. Es ist etwas , das Sie write() zu . lessEs muss nichts anders gemacht werden, je nachdem, ob es sich bei der Ausgabe um eine Datei, eine Pipe, einen Socket oder ein Block-Gerät handelt oder was auch immer. Es ist nur wichtig, dass es kein tty ist, also verhält es sich einfach so cat. (Ich nehme an, Sie wussten das und wählten nur die falschen Wörter, um es zu erklären, aber ich dachte, ich würde dies für andere Leser herausstellen).
Peter Cordes
Sie meinen, es ist die Aufgabe von weniger, sich in meiner speziellen Frage wie eine Katze zu verhalten - oder allgemeiner: sich wie der nächste Befehl in einer Pipeline zu verhalten. Nach meinem Verständnis kann ich nicht davon ausgehen, dass das exakt gleiche Verhalten auch in einem anderen Tool implementiert ist.
31.
@tfh: Nein, " lessfindet" nicht heraus, was catals nächstes kommt. Es verhält sich einfach so, catunabhängig davon, wie es weitergeht, wenn es kein tty ist.
Peter Cordes
@MichaelD .: danke, korrigiert meine antwort. Ich habe nur vermutet, dass lessdies mit einem TCGETS möglich ist, um die Terminaldimensionen zu ermitteln oder festzustellen, dass es sich nicht um eine Tty handelt, aber anscheinend habe ich falsch geraten.
Peter Cordes
6

lessüberprüft, ob stdoutes sich um ein Terminal handelt und verhält sich so, catals wäre es nicht vorhanden (kopiert stdin nach stdout bis EOF).

Mit dieser Funktion können Sie Skripte oder Programme schreiben, die ihre Ausgabe immer senden (z. B. --helpAusgabe), lesswährend die einfache Umleitung in eine Datei weiterhin möglich ist. Es wäre scheiße, wenn man some_command --fullhelp > help.txtimmer noch darauf warten würde, dass die Leertaste auf stdin durch den Text blättert oder so. Einige Befehle (z. B. man) prüfen die eigene Ausgabe, um zu entscheiden, ob die Ausgabe über einen Pager gesendet wird oder nicht. Wenn du rennst man ls > ls.txt, ruft es niemals deine $PAGER.

lessDas katzeähnliche Verhalten von ist praktisch, wenn Sie vergessen, es aus einem Einzeiler heraus zu bearbeiten, wenn Sie einer Pipeline auch mehr Stufen hinzufügen.


lessmuss die Terminalabmessungen ermitteln (Bildschirmgröße, um zu wissen, wie viele Zeilen gleichzeitig angezeigt werden sollen). Die ioctl(2)nutzt auf stdoutwürde ENOTTY auf einem Nicht-Terminal zurückkehren, so dass es die nicht-Terminal Sachbearbeitung ohnehin nicht vermeiden kann. Wird lesstatsächlich verwendet, isatty(3)bevor die Terminalabmessungen überprüft werden. isattyDies funktioniert jedoch, indem ein reines tty-ioctl ausgeführt und auf Fehlerfreiheit überprüft wird.

Sogar ein einfacher Pager wie more(1)(zumindest die Util-Linux-Version) hat diese Funktion, da es wahrscheinlich das einfachste vernünftige Verhalten ist, das für diesen Fall implementiert werden kann.


Beachten Sie, dass beim Pipe- In less (z. B. grep foo bar.txt | less) etwas /dev/ttyfür die Tastatureingabe geöffnet werden muss. (Sie können sehen, dass es dies mit tut echo foo | strace less).

Peter Cordes
quelle