2014-02-13 2 views
4

Я пытаюсь использовать tput в сценарии Bash и прилагаю все усилия, чтобы избежать случайной ошибки. С этой целью я написал следующую строку:Любопытное поведение tput, с перенаправлением stderr

COLS="$(tput cols 2> /dev/null)" 

К моему удивлению, когда я запускаю это, COLS не последовательно устанавливаются в 80, независимо от того, что ширина моего окна терминала случается. (. Ради демонстрации, мой терминал случается 115 столбцов в ширину) Для того, чтобы выяснить, что происходит, я попробовал несколько вещей, в командной строке:

$ tput cols 
115 
$ tput cols | cat 
115 
$ echo "$(tput cols)" 
115 
$ tput cols 2> /dev/null 
115 
$ echo "$(tput cols 2> /dev/null)" 
80 

Так, tput кажется, успех при определении характеристик терминала при перенаправлении его stderr или при встраивании в процесс замещения, но не в обоих. Как странно!

Я тестировал это как на Linux, так и на OS X, и поведение такое же.

Что здесь происходит? И как практический вопрос, что лучший способ получить tput для работы при подавлении stderr spew?

Примечание: я знаю о $COLUMNS. Меня особенно интересует использование tput.

+0

То же поведение в 'zsh',' dash' и 'ksh', поэтому это будет выглядеть независимо от оболочки, используемой для запуска' tput'. – chepner

ответ

5

Быстрая strace перспектива предполагает, что tput пытается определить ширину вывода на stdout первом, и если это не удается, он возвращается к stderr. Итак, в случае отказа оба перенаправлены, а tput (по-видимому) принимает значение по умолчанию 80 столбцов.

0

Google привел меня сюда, поскольку у меня была аналогичная проблема. Хотя принятый ответ действительно отвечает на вопрос, он действительно не предлагает никаких предложений о том, как работать с ошибкой, упомянутой в исходном вопросе. Думал, что я позвоню с возможной работой.

Моей конкретной ситуацией является создание сценариев, которые можно вызывать из командной строки или из cron. При запуске из cron Solaris устанавливает переменную TERM в «тупой», о которой tput ничего не знает, и она выводит ошибки (которые отправляются почтовому отправителю владельцу задания cron). Поскольку вы не можете поймать ошибки и stdout, чтобы получить количество столбцов, я сначала попытался выяснить способ определения того, знает ли tput об определенном терминале, перед запуском tput cols. С этой целью, этот код кажется служить своей цели:

declare TPUT C 
TPUT="$(tput longname 2>/dev/null)" 
[[ "$TPUT" ]] && C="$(tput cols)" 
C=${C:-80} 

Я понимаю, что это не будет перехватывать все ошибки, но по крайней мере, уклоняется ошибки можно, если tput не знает о конкретном терминале.

Смежные вопросы