Ответ 1
Вы можете получить строки и столбцы от tput
:
#!/bin/bash
lines=$(tput lines)
columns=$(tput cols)
echo "Lines: " $lines
echo "Columns: " $columns
Рассмотрим следующее:
[email protected]:~$ cat a.sh
#!/bin/bash
echo "Lines: " $LINES
echo "Columns: " $COLUMNS
[email protected]:~$ ./a.sh
Lines:
Columns:
[email protected]:~$ echo "Lines: " $LINES
Lines: 52
[email protected]:~$ echo "Columns: " $COLUMNS
Columns: 157
[email protected]:~$
Переменные $LINES
и $COLUMNS
являются переменными оболочки, не переменными окружения и, следовательно, не экспортируются в дочерний процесс (но они автоматически обновляются, когда я изменяю размер окна xterm, даже при входе в систему через ssh из удаленного места). Есть ли способ, позволяющий моему script узнать текущий размер терминала?
EDIT:
Мне нужно это в качестве решения этой проблемы: vi (а также vim, less и подобные команды) каждый раз испортит экран каждый раз, когда я его использую. Изменение терминала не является вариантом, и поэтому я ищу обходные пути (прокрутка вниз $LINES
строк, безусловно, не идеальное решение, но по крайней мере лучше, чем потерять предыдущий экран)
Вы можете получить строки и столбцы от tput
:
#!/bin/bash
lines=$(tput lines)
columns=$(tput cols)
echo "Lines: " $lines
echo "Columns: " $columns
kill -s WINCH $$
устанавливает переменные.
eval $( resize )
выполняет эту работу... (на терминале на основе xterm)
Попробовали ли вы заставить свой shebang сказать:
#!/bin/bash -i
Может ли работать help export
?
[email protected]:~$ cat a.sh
#!/bin/bash
echo "Lines: " $LINES
echo "Columns: " $COLUMNS
[email protected]:~$ ./a.sh
Lines:
Columns:
[email protected]:~$ echo "Lines: " $LINES
Lines: 52
[email protected]:~$ echo "Columns: " $COLUMNS
Columns: 157
[email protected]:~$ export LINES COLUMNS
[email protected]:~$ ./a.sh
Lines: 52
Columns: 157
[email protected]:~$
$LINES
и $COLUMNS
в bash - это всего лишь оболочка-оболочка вокруг TTY ioctls, дающая вам размер TTY и сигналы, посылаемые терминалом каждый раз, когда этот размер изменяется.
Вы можете написать программу на другом языке, который вызывает эти ioctls напрямую, чтобы получить размеры TTY, а затем использовать эту программу.
EDIT: Ну, оказывается, что программа уже существует и называется tput
. Голосовать Puppe tput
на основе ответа.
#!/bin/bash -i
-i
теперь работает с bash 4.2.10 (1) -release на Ubuntu 11.10.
$ cat show_dimensions.sh
#!/bin/bash -i
printf "COLUMNS = %d\n" $COLUMNS
printf "LINES = %d\n" $LINES
$ ./show_dimensions.sh
COLUMNS = 150
LINES = 101
$ bash --version
GNU bash, version 4.2.10(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Числа изменяются с изменением размера окна; ловушка показывает, что script получает SIGWINCH.
Поскольку этот вопрос популярен, я хочу добавить более новый ответ с дополнительной информацией.
Переменные $COLUMNS
и $LINES
не являются переменными среды. Эти значения динамически устанавливаются оболочкой после каждой команды, и мы обычно не можем получить к ней доступ из неинтерактивных скриптов.
Bash устанавливает эти переменные, когда мы включаем параметр checkwinsize
, используя:
shopt -s checkwinsize
Во многих системах этот параметр используется для файла по умолчанию или для всего системного файла (bashrc), поэтому нам нужно помнить, что эти переменные могут быть недоступны. В некоторых системах, таких как Cygwin, эта опция не включена для нас, поэтому Bash не устанавливает $COLUMNS
и $LINES
, если мы не выполним строку выше или не добавим ее в наш .bashrc.
При написании неинтерактивных скриптов мы не можем использовать $LINES
и $COLUMNS
по умолчанию. Вместо этого утилиты stty
и tput
предоставляют переносные средства для определения размера терминала из script (ниже описаны команды которые в настоящее время проходят стандартизацию для POSIX).
Как показано в текущем принятом ответе, мы можем использовать tput
, чтобы собрать размер терминала довольно просто:
lines=$(tput lines)
columns=$(tput columns)
В качестве альтернативы запрос size
для stty
дает нам количество строк и столбцов терминала за один шаг (выводится как число столбцов, за которыми следуют два пробела, за которыми следует количество строк):
size=$(stty size) # "80 40" for example
Я иногда предпочитаю подход stty
, потому что мы вызываем еще одну команду и подоболочку (дорогостоящую на Cygwin), но она требует, чтобы мы анализировали вывод в строках и столбцах, что может быть менее читаемым:
lines=${size#* }
columns=${size% *}
Оба подхода, описанные выше, работают в любой оболочке POSIX. Для Bash в частности, мы можем использовать замещение процесса, чтобы упростить предыдущий пример:
read columns lines < <(stty size)
... который работает быстрее, чем пример tput
, но все же медленнее, чем первая реализация stty
, по крайней мере, на моей машине. На практике влияние производительности, вероятно, незначительно - выберите подход, который лучше всего подходит для программы (или на основе того, какая команда доступна в целевой системе).
Если по каким-то причинам мы хотим использовать $LINES
и $COLUMNS
в наших сценариях, мы можем настроить Bash для экспорта этих переменных в среду:
trap 'export LINES COLUMNS' DEBUG
Ловушка DEBUG
выполняется перед каждой командой, введенной в приглашении, поэтому мы можем использовать ее для экспорта этих переменных. Посредством повторного экспорта их после каждой команды мы гарантируем, что переменные среды будут обновлены, если размер терминала изменится. Добавьте эту строку в .bashrc. Он отлично работает для личных скриптов, но я не рекомендую использовать эти переменные в любом script, который будет использоваться совместно.