mniej plik1 plik2 | kot - dlaczego to działa?

21

Kiedy używam less file1 file2, oba pliki są wyświetlane w „przeglądarce mniej buforów”, ale less file1 file2 | catdrukuje zawartość obu plików dołączonych do standardowego wyjścia. Skąd mniej wie, czy powinien wyświetlać „przeglądarkę mniej buforów” czy generować wyjście na standardowe wyjście dla następnego polecenia? Jaki mechanizm służy do tego?

tfh
źródło

Odpowiedzi:

30

lessdrukuje tekst na standardowe wyjście. stdout idzie

  • do terminala (/ dev / tty?) i otwiera domyślną przeglądarkę buforów
  • przez potok podczas przesyłania go do innego programu za pomocą | ( less text | cut -d: -f1)
  • do pliku podczas przekierowania go za pomocą> ( less text > tmp)

Istnieje funkcja C o nazwie „isa tty ”, która sprawdza, czy wyjście przechodzi do tty (mniej 4.81, main.c, linia 112). Jeśli tak, używa przeglądarki buforów, w przeciwnym razie zachowuje się jak cat.

W bash możesz użyć testu (patrz man test)

  • -t Deskryptor pliku FD FD jest otwarty na terminalu
  • -p PLIK istnieje i jest nazwanym potokiem

Przykład:

[[ -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.
źródło
1
@ tfh Jeśli STDOUT nie jest dołączony do potoku lub przekierowania, poprawne jest, aby nie drukowały, że STDOUT jest dołączony do potoku lub przekierowania. Umieść wszystkie trzy w skrypcie. Wezwanie bash script.sh, bash script.sh | cat, bash script.sh > file, i zobaczyć, co wyjście dostać.
hvd
1
stdoutnie jest czymś, co można „zapisać do pliku”. To jest coś write() do ciebie . lessnie musi robić nic inaczej w zależności od tego, czy jego wyjściem jest plik, potok, gniazdo, urządzenie blokowe, czy cokolwiek innego. Liczy się tylko to, że nie jest tty, więc po prostu się zachowuje cat. (Zakładam, że o tym wiedziałeś i po prostu wybrałeś niewłaściwe słowa, aby to wyjaśnić, ale pomyślałem, że wskazałbym to innym czytelnikom).
Peter Cordes
Masz na myśli, że zadaniem mniej jest zachowywać się jak kot w moim konkretnym pytaniu - lub bardziej ogólnie: zachowywać się jak następne polecenie w potoku. Z tego, co zrozumiałem, nie mogę założyć, że dokładnie to samo zachowanie jest realizowane także w innym narzędziu.
tfh
@ tfh: Nie, lessnie „ wymyśla ”, co catbędzie dalej. Po prostu zachowuje się jak catniezależnie od tego, co będzie dalej, jeśli jego standardowe wyjście nie jest tty.
Peter Cordes
@MichaelD .: dzięki, poprawiłem moją odpowiedź. Właśnie lesszgadłem, że skorzystam z jednego TCGETS, aby uzyskać wymiary terminala lub odkryć, że to nie jest tty, ale najwyraźniej pomyliłem się.
Peter Cordes
6

lesssprawdza, czy stdoutjest to terminal i zachowuje się tak, jak catnie jest (kopiuje standardowe wejście na standardowe wyjście, aż do EOF).

Ta funkcja pozwala pisać skrypty lub programy, które zawsze wysyłają dane wyjściowe (np. Dane --helpwyjściowe), lessjednocześnie umożliwiając łatwe przekierowanie do pliku. Byłoby do bani, gdyby some_command --fullhelp > help.txtnadal czekał na spację na stdin, aby przewinąć tekst lub coś w tym rodzaju. Niektóre polecenia (np. man) Sprawdzają, czy ich dane wyjściowe decydują, czy wysłać dane wyjściowe za pomocą pagera, czy nie. Jeśli biegniesz man ls > ls.txt, nigdy nie wywołuje twojego $PAGER.

lessZachowanie przypominające kota jest przydatne, jeśli zapomnisz edytować go z jednej linii podczas dodawania kolejnych etapów do rurociągu.


lessmusi obliczyć wymiary terminala (rozmiar ekranu, aby wiedzieć, ile linii ma pokazać jednocześnie). ioctl(2)Używa on stdoutwróci ENOTTY na non-końcowy, więc nie można uniknąć manipulowania niekońcową sprawę tak. lessfaktycznie używa isatty(3)przed sprawdzeniem wymiarów terminala, ale isattydziała, próbując ioctl-a tylko tty i sprawdzając brak błędu.

Nawet prosty pager jak more(1)(przynajmniej wersja util-linux) ma tę funkcję, ponieważ jest to prawdopodobnie najprostsze rozsądne zachowanie, które można zastosować w tym przypadku.


Zauważ, że kiedy wpinasz coś do less (np. grep foo bar.txt | less), Musi się otwierać /dev/ttyna klawiaturę. (Możesz to zobaczyć za pomocą echo foo | strace less).

Peter Cordes
źródło