менше file1 file2 | кішка - чому це працює?


21

Коли я запускаю, less file1 file2я отримую обидва файли, що відображаються у "перегляді менш буфера", але less file1 file2 | catдрукує вміст обох файлів, доданих до stdout. Звідки менше знати, чи повинен він показувати "менше переглядача буфера" або виробляти вихід для stdout для наступної команди? Який механізм використовується для цього?

Відповіді:


30

lessдрукує текст до stdout. stdout іде

  • до терміналу (/ dev / tty?) і відкриває переглядач буфера за замовчуванням
  • через трубу під час передачі її до іншої програми за допомогою | ( less text | cut -d: -f1)
  • до файлу, перенаправляючи його за допомогою> ( less text > tmp)

Існує функція C під назвою "isa tty ", яка перевіряє, чи буде вихід на tty (менше 4.81, main.c, рядок 112). Якщо так, то він використовує переглядач буфера, інакше він поводиться так cat.

У bash ви можете використовувати тест (див. man test)

  • -t Дескриптор файлу FD FD відкривається на терміналі
  • -p FILE існує і є іменованою трубою

Приклад:

[[ -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'

1
@tfh Якщо STDOUT не приєднаний до труби або перенаправлення, правильно, що вони не друкують, що STDOUT приєднано до труби або перенаправлення. Покладіть усі три в сценарій. Виклик bash script.sh, bash script.sh | cat, bash script.sh > fileі подивитися , що висновок , який ви отримаєте.
hvd

1
stdoutце не те, що можна "записати у файл". Це те , що вам write() в . lessне потрібно робити нічого інакше, залежно від того, чи є його вихідним файлом, трубою, сокетом чи блоковим пристроєм чи іншим способом. Важливо лише, що це не tty, тому воно просто так поводиться cat. (Я припускаю, що ви це знали і просто вибрали неправильні слова, щоб пояснити це, але я подумав, що я зазначу це іншим читачам).
Пітер Кордес

Отже, ви маєте на увазі, що в моєму конкретному питанні - менше поводитись як кішка - чи більш загально: поводитись як наступна команда в конвеєрі. З того, що я зрозумів, я не можу припустити, що точно така ж поведінка реалізована і в іншому інструменті.
tfh

@tfh: Ні, lessне "з'ясовується", що catдалі. Він просто поводиться, як і catнезалежно від того, що далі, якщо stdout не є tty.
Пітер Кордес

@MichaelD.: Спасибі, виправили свою відповідь. Я просто здогадався, що lessбуде далі і використовувати один TCGETS, щоб отримати термінальні розміри або виявити, що це не tty, але, мабуть, я здогадався неправильно.
Пітер Кордес

6

lessперевіряє, чи stdoutє терміналом, і поводиться так, catяк ні (копіює stdin до stdout до EOF).

Ця функція дозволяє писати сценарії чи програми, які завжди надсилають свої результати (наприклад, --helpвихідні дані), lessодночасно дозволяючи просте перенаправлення до файлу. Це буде смоктати, якби some_command --fullhelp > help.txtвсе-таки чекали, коли пробіл на stdin перегортає текст, або щось таке. Деякі команди (наприклад man) перевіряють, чи є їх власний вихід, щоб вирішити, надсилати свій вихід через пейджер чи ні. Якщо ви біжите man ls > ls.txt, він ніколи не викликає ваш $PAGER.

lessповедінка як котяча корисна, якщо ви забудете відредагувати її з однолінійки, додаючи ще кілька етапів до конвеєра.


lessпотрібно розібрати кінцеві розміри (розмір екрана, щоб знати, скільки рядків показувати одразу). Використання, яке ioctl(2)він використовує stdout, поверне ENOTTY на нетермінальний, так що не може уникнути обробки ненетермінального випадку. lessнасправді використовується isatty(3)до перевірки термінальних розмірів, але isattyпрацює, намагаючись лише tty-ioctl і перевіряє відсутність помилок.

Навіть простий пейджер на зразок more(1)(принаймні версія util-linux) має цю особливість, оскільки це, мабуть, найпростіша розумна поведінка, яку можна реалізувати для цього випадку.


Зауважте, що коли ви щось вставляєте less (наприклад grep foo bar.txt | less), це потрібно відкривати /dev/ttyдля введення з клавіатури. (Ви можете бачити, як це можна зробити echo foo | strace less).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.