请考虑以下事项:
me@mine:~$ cat a.sh
#!/bin/bash
echo "Lines: " $LINES
echo "Columns: " $COLUMNS
me@mine:~$ ./a.sh
Lines:
Columns:
me@mine:~$ echo "Lines: " $LINES
Lines: 52
me@mine:~$ echo "Columns: " $COLUMNS
Columns: 157
me@mine:~$
变量$LINES
和$COLUMNS
是shell变量,不是环境变量,因此不会导出到子进程(但是当我调整大小时,它们会自动更新xterm窗口,即使从远程位置通过ssh登录也是如此)。有没有办法让我的脚本知道当前的终端大小?
编辑:
我需要这个作为解决方法做this problem:vi(以及vim,less和类似命令)每次使用它时都会弄乱屏幕。更改终端不是一个选项,因此我正在寻找变通方法(向下滚动$LINES
行肯定不是完美的解决方案,但至少比丢失前一个屏幕更好)
答案 0 :(得分:78)
您可以从tput
获取行和列:
#!/bin/bash
lines=$(tput lines)
columns=$(tput cols)
echo "Lines: " $lines
echo "Columns: " $columns
答案 1 :(得分:18)
因为这个问题很受欢迎,所以我想添加一个更新的答案和一些额外的信息。
通常,在现代系统中,$COLUMNS
和$LINES
变量是不是环境变量。 shell在每个命令之后动态设置这些值,我们通常无法从非交互式脚本访问它们。如果我们 export 它们,某些程序会尊重这些值,但这种行为不是标准化的或普遍支持的。
当我们使用以下命令启用checkwinsize
选项时,Bash会将这些变量设置在进程(而非环境)的范围内:
shopt -s checkwinsize
许多系统在默认或系统范围的启动文件( / etc / bashrc 或类似的)中为我们启用此选项,因此我们需要记住这些变量可能并不总是可用。在某些系统上,例如Cygwin,此选项为我们启用 ,因此Bash不设置$COLUMNS
和$LINES
,除非我们执行上面的行或将其添加到我们的〜/ .bashrc 。
在编写非交互式脚本时,我们通常不希望默认依赖$LINES
和$COLUMNS
(但我们可以检查这些以允许用户如果需要,手动覆盖终端尺寸。)
相反,stty
和tput
实用程序提供 portable 意味着从脚本确定终端大小(下面描述的命令是currently undergoing standardization for POSIX)。< / p>
如Puppe所接受的答案所示,我们可以使用tput
以非常简单的方式收集终端尺寸:
lines=$(tput lines)
columns=$(tput cols)
或者,对size
的{{1}}查询在一步中为我们提供终端行和列的数量(输出为行数,后跟两个空格,后跟列数): / p>
stty
size=$(stty size) # "40 80" for example
程序通常附带GNU Coreutils,因此我们经常可以在没有stty
的系统上找到它。我有时更喜欢tput
方法,因为我们调用一个较少的命令和子shell(在Cygwin上很昂贵),但它确实要求我们将输出解析为行和列,这可能不太可读:
stty
上述两种方法都适用于任何POSIX shell。特别是对于Bash,我们可以使用process substitution来简化前面的示例:
lines=${size% *}
columns=${size#* }
...比read lines columns < <(stty size)
示例运行得更快,但仍然比第一个tput
实施慢,至少在我的机器上。在实践中,性能影响可能是微不足道的 - 选择最适合程序的方法(或基于目标系统上可用的命令)。
如果由于某种原因,我们仍希望在脚本中使用stty
和$LINES
,我们可以配置Bash将这些变量导出到环境中:
$COLUMNS
Bash trap 'export LINES COLUMNS' DEBUG
陷阱在提示输入的每个命令之前执行,因此我们可以使用它来导出这些变量。通过使用每个命令重新导出它们,我们确保在终端大小更改时环境变量保持最新。将此行添加到 .bashrc 以及上面显示的DEBUG
选项。它适用于个人脚本,但我不建议在任何将共享的脚本中使用这些变量。
答案 2 :(得分:6)
eval $( resize )
完成这项工作......(在基于xterm的终端上)
答案 3 :(得分:5)
kill -s WINCH $$
设置变量。
答案 4 :(得分:4)
为了完成,我要提一下,设置'checkwinsize'选项正是OP正在寻找的,但有一个问题。默认情况下,它在非交互式脚本中未设置,但您可以选择在任何脚本的开头添加以下行以启用它:
shopt -s checkwinsize
不幸的是,LINES和COLUMNS变量在设置选项时没有立即设置(至少我上次尝试时)。相反,您需要强制Bash等待子shell完成,此时它将设置这些变量。因此,针对此问题的完全Bash解决方案是使用以下行启动脚本:
shopt -s checkwinsize; (:;:)
然后,您可以将LINES和COLUMNS变量用于您的内容,每次调整终端大小时,它们都将重置为正确的值,而无需调用任何外部实用程序。
答案 5 :(得分:2)
你试过让你的shebang说:
#!/bin/bash -i
答案 6 :(得分:2)
运行help export
可能有帮助吗?
me@mine:~$ cat a.sh
#!/bin/bash
echo "Lines: " $LINES
echo "Columns: " $COLUMNS
me@mine:~$ ./a.sh
Lines:
Columns:
me@mine:~$ echo "Lines: " $LINES
Lines: 52
me@mine:~$ echo "Columns: " $COLUMNS
Columns: 157
me@mine:~$ export LINES COLUMNS
me@mine:~$ ./a.sh
Lines: 52
Columns: 157
me@mine:~$
答案 7 :(得分:1)
$LINES
和$COLUMNS
只是围绕TTY ioctls的shell-y包装器,它为您提供TTY的大小以及每次大小更改时终端发送的信号。
您可以使用其他语言编写程序,直接调用这些ioctl以获取TTY维度,然后使用该程序。
编辑:嗯,事实证明该程序已经存在,并被称为tput
。投票Puppe's tput
based answer。
答案 8 :(得分:1)
#!/bin/bash -i
-i
现在可以在 Ubuntu 11.10 上使用 bash 4.2.10(1)-release 工作。
$ 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.
数字会随着窗口调整大小而改变;陷阱显示脚本正在获得SIGWINCH。
答案 9 :(得分:0)
为什么不在exec命令上使用环境变量,如下所示:
docker exec -ti -e LINES=$LINES -e COLUMNS=$COLUMNS container /bin/bash
答案 10 :(得分:-1)
我的经验是你应该通过&#39;来启动脚本。 script_to_run&#39;形式,而不是'scritp_to_run&#39;。一个简单的检查如下:
'(( ${#COLUMNS} )) || { echo "Try start like '. name'" ; return 1 ; }