Как передать стандартный вывод, сохраняя его на экране? (а не в выходной файл)

234

Я хотел бы передать стандартный вывод программы, сохраняя ее на экране.

С простым примером ( echoиспользуйте здесь только для иллюстрации):

$ echo 'ee' | foo
ee <- вывод, который я хотел бы увидеть

Я знаю, что можно скопировать стандартный вывод в файл, но это не то, что я хочу.
$ echo 'ee' | tee output.txt | foo

Я пытался,
$ echo 'ee' | tee /dev/stdout | fooно это не работает, так как выход тройника /dev/stdoutкfoo

gentooboontoo
источник
6
Обратите внимание, что это echo 'ee' | tee /dev/stderrработает, поэтому, если ваше требование "на экране" удовлетворяется и stderr, это подойдет.
nh2

Ответы:

344

Вот решение, которое работает в любой реализации Unix / Linux, при условии, что оно будет следовать POSIXстандарту. Это работает в некоторых не Unix средах, как cygwinтоже.

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

Ссылка: Открытая группа базовых спецификаций, выпуск 7 IEEE Std 1003.1, издание 2013 г., §10.1 :

/ DEV / TTY

Связанный с группой процессов этого процесса, если таковые имеются. Это полезно для программ или процедур оболочки, которые хотят быть уверенными в записи сообщений или чтении данных с терминала, независимо от того, как перенаправлен вывод. Он также может быть использован для приложений, которые требуют имя файла для вывода, когда требуется типизированный вывод, и утомительно выяснять, какой терминал используется в настоящее время. В каждом процессе синоним управляющего терминала

Сообщалось, что некоторые среды, такие как Google Colab, не реализуются, /dev/ttyхотя их ttyкоманда возвращает работоспособное устройство. Вот обходной путь:

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

или с древней скорлупой Борна:

tty=`tty`
echo 'ee' | tee $tty | foo
jlliagre
источник
5
@static_rtti Почему вы из года в год игнорируете мои ответы на ваш комментарий?
Jlliagre
1
@PaulBissex /dev/tty- обязательное устройство Unix. Вы работаете в тюрьме BSD?
Jlliagre
1
@PaulBissex Это либо ошибка реализации, либо ошибка конфигурации. Установлен ли / dev? Что показывает "ls -l / dev / tty / dev / tty * / dev"? См. Lists.freebsd.org/pipermail/freebsd-bugs/2012-November/… forums.freebsd.org/threads/…
jlliagre
1
И вы можете сделать teeэто следующим образом: cat some.log | tee /dev/tty | tee -a other.log | grep -i 'foo' >> foo.log1) получить все это на консоли, 2) fooдобавить все это в другой файл, 3) получить строки в другой файл.
Джесси Чисхолм
1
Google Colab не имеет /dev/tty, но вывод ttyможно использовать.
Том Хейл
69

Еще одна вещь, чтобы попробовать это:

echo 'ee' | tee >(foo)

>(foo)Является замена процесса .

БМК
источник
1
Что делать, если я хочу передать вывод foo в другой бар?
Джек Тан
3
@JackTang - я думаю, что дальнейшая передача по выходу fooдолжна быть частью процесса замещения. Вот пример:echo 'ee' | tee file.txt >(wc -c | tr -d ' ')
Ник Чаммас
1
Это было решением для меня на FreeBSD (нет / dev / tty)
Пол Биссекс
9
@Nick Хаммас, чтобы поддерживать нормальный трубопровод, вы можете поменять местами выходы тройника: echo 'ee' | tee >(cat) | foo | bar.
Вэлос
18

Доступ к "/ dev / stdout" запрещен в некоторых системах, но доступ к пользовательскому терминалу предоставляется "/ dev / tty". Используя "wc" для "foo", приведенные выше примеры работают нормально (на linux, OSX и т. Д.) Как:

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

Чтобы добавить счетчик внизу списка подходящих файлов, я использую что-то вроде:
% ls [A-J]* | tee /dev/tty | wc -l

Чтобы избежать необходимости помнить все это, я определяю псевдонимы:
% alias t tee /dev/tty
% alias wcl wc -l

так что я могу просто сказать:
% ls [A-J]* | t | wcl


ПОСТСКРИПТ: Для младшего набора, который мог бы титровать в своем произношении как «сиська», я мог бы добавить, что «tty» когда-то было распространенным сокращением термина «телетайп», который использовал рулон желтой бумаги и имел круглые ключи, которые часто застрял.

user51527
источник
17

Пытаться:

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

Если использование stderr это вариант, конечно.

январь
источник
8

сначала вам нужно выяснить терминал, связанный с вашим экраном (или любым экраном, на котором вы хотите выводить вывод):

tty

затем вы можете передать вывод на этот терминал и передать другую копию через вашу программу foo:

echo ee | tee /dev/pty/2 | foo
Майкл Мартинес
источник
1
oneliner: t = $ (tty) echo ee | тройник $ t | фу | бар
Джек Тан
5
@JackTang Это действительно лучше, но tбесполезно. Вы можете использовать, echo ee | tee $(tty) | fooно он по-прежнему имеет бесполезную команду ( tty), учитывая тот факт, /dev/ttyчто просто работает.
Jlliagre