Я попробовал следующую команду после просмотра этого видео на трубе махинаций.
man -k . | dmenu -l 20 | awk '{print $1}' | xargs -r man -Tpdf | zathura -
Он в основном выводит список man-страниц в dmenu, чтобы пользователь мог выбрать один из них, затем использует xargs для запуска man -Tpdf %
(печать выводит PDF-файл man-страницы из ввода xargs) и передает pdf в программу чтения PDF (zathura). ).
Проблема в том, что (как вы можете видеть на видео) программа чтения PDF запускается еще до того, как я выбрал одну страницу в dmenu. И если я нажму «Esc» и не выберу ни один, программа чтения PDF-файлов все еще будет открыта, не показывая никакого документа.
Как я могу заставить программу чтения PDF (и любую другую команду в цепочке конвейеров) запускаться только тогда, когда ее ввод достигает конца файла или когда он вообще получает ввод? Или, в качестве альтернативы, как заставить цепочку конвейера остановиться после того, как одна из цепочечных команд вернет ненулевой статус выхода (так что если dmenu вернет ошибку из-за отсутствия выбора опции, следующие команды не будут выполнены)?
источник
pipefail
опции bash, упомянутой в ответе Кусаланданды.Ответы:
Есть
ifne
(в Debian он есть вmoreutils
пакете):В твоем случае:
источник
moreutils
) должна была быть в исходном Unix и определена posix ... Это такой базовый и Unix-иш инструмент ...ifne
немного обманчива. Unix не имеет операции "pipe peek", поэтомуifne
фактически должен прочитать хотя бы один байт, прежде чем принять решение запустить зависимую команду. Это означает, что он не может просто выполнить тест и выполнить команду, но должен создать другой канал, запустить другой процесс для запуска зависимой команды и скопировать весь поток из канала stdin в канал ниже по потоку. Если случай «ввода пуст» не является распространенным явлением, онifne
может легко стоить в среднем больше ресурсов, чем экономит.PDF-файлы должны быть доступны для поиска; любой просмотрщик PDF должен сначала посмотреть на трейлер, а затем перейти к смещению из таблицы внешних ссылок.
Поскольку каналы недоступны для поиска,
zathura
используется запутывающий трюк, при котором все входные данные копируются во временный файл, а затем используется этот временный файл, как обычно. Этот вид «умного» трюка создает ложные надежды и заставляет людей предполагать, что PDF-файлы пригодны для чтения.Но в любом случае, на
zathura
самом деле делает ожидание для EOF перед отображением документа, вам не нужно ничего делать для того , чтобы hapen:Проблема в том, что
zathura
нет возможности открывать окно, только если файл в порядке, и выходить с ошибкой, если это не так, - он просто останется там, как будто все в порядке:Таким образом, даже если вы перенаправляете вывод во временный файл самостоятельно и работаете, только
zathura
если все было в порядке, нет гарантии, что пользователю не будет предоставлено черное окно, еслиzathura
ему не нравится вывод по той или иной причине. ,Btw,
отобразит man-страницу в окне X11
gxditview
, даже если она выглядит прямо из '70 ;-)И, конечно же, вы всегда можете использовать:
что, помимо многих других улучшений, позволит вам использовать регулярные выражения при поиске и правильном выборе текста.
источник
Все команды в конвейере запускаются практически одновременно. Это только ввод-вывод по каналу, который синхронизирует их. Кроме того, канал может содержать только столько информации, сколько позволяет буфер канала.
Поэтому вы не можете избежать запуска одной стадии конвейера, потому что
Вместо этого запишите вывод в файл, позволяя конвейеру завершиться. Затем используйте этот файл.
Пример (как функция, принимающая один аргумент):
Это дополнительно не будет запускать
zathura
программу, если конвейер завершится неудачно (xargs
деталь вернула ненулевое значение) или сгенерированный файл будет пустым.В
bash
оболочке вы также можете установить параметрpipefail
оболочки так,set -o pipefail
чтобы конвейер возвращал состояние выхода первой команды в конвейере, которая завершилась неудачно. И вы хотели бы сделатьtmpfile
переменнуюlocal
:Это устанавливает
pipefail
параметр для продолжительности функции, если она еще не была установлена, а затем отменяет ее, если необходимо. Избавляется от-s
теста в выходном файле.источник
rm -f
? Вы думаете о случаях, когда канал изменяет права доступа к tmpfile?rm -f
не будет ошибки, если файл уже был удален (возможноzathura
, я не знаю).pipefail
опцией работает как положено (и в zsh, которая имеет такую же опцию).