因为这个问题很受欢迎,所以我想添加一个新的答案以及一些其他信息。
通常,在现代系统上,$COLUMNS
和$LINES
变量不是环境变量。Shell在每个命令之后动态设置这些值,我们通常无法从非交互式脚本访问它们。如果我们导出这些值,有些程序会尊重这些值,但是这种行为并未得到标准化或普遍支持。
当我们使用以下方法启用该选项时,Bash会在流程范围(而非环境)中设置这些变量checkwinsize
:
shopt -s checkwinsize
许多系统在默认或系统范围的启动文件(/ etc / bashrc或类似文件)中为我们启用此选项,因此我们需要记住,这些变量可能并不总是可用。在某些系统上,例如Cygwin,我们未启用此选项,因此不会设置Bash $COLUMNS
,$LINES
除非我们执行上面的行或将其添加到〜/ .bashrc中。
便携式方法
当写非交互式脚本,我们通常不希望依赖于$LINES
和$COLUMNS
默认情况下(但我们可以检查这些允许如果需要,用户可以手动覆盖终端大小)。
而是,stty
和tput
实用程序提供了一种可移植的方法,可以根据脚本确定终端大小(以下描述的命令当前正在针对POSIX进行标准化)。
如Puppe接受的答案所示,我们可以用tput
一种非常简单的方式来收集终端大小:
lines=$(tput lines)
columns=$(tput cols)
或者,size
查询可以stty
一步一步给我们提供终端行和列的数量(输出为行数,后跟两个空格,后跟列数):
size=$(stty size)
该stty
程序通常与GNU Coreutils一起提供,因此我们经常可以在没有的系统上找到它tput
。有时我更喜欢这种stty
方法,因为我们调用的命令和子外壳要少一些(在Cygwin上很昂贵),但是它确实要求我们将输出解析为行和列,因此可读性较差:
lines=${size% *}
columns=${size#* }
上述两种方法都可以在任何POSIX Shell中使用。
非便携式方法
如果我们不在乎可移植性,那么Bash支持流程替换以简化前面的示例:
read lines columns < <(stty size)
...比tput
示例运行得更快,但stty
至少在我的机器上仍比第一个实现慢。实际上,对性能的影响可以忽略不计-选择最适合该程序的方法(或基于目标系统上可用的命令)。
对于Bash 4.3和更高版本,我们可以利用该checkwinsize
选项来避免依赖于另一个程序。当我们在脚本中启用此选项时,在子进程退出后,Bash会进行设置$LINES
,$COLUMNS
就像在交互式提示中一样:
#!/bin/bash
shopt -s checkwinsize
cat /dev/null
...就像子外壳退出时一样:
shopt -s checkwinsize
(: Refresh LINES and COLUMNS)
如果启用此选项,Bash将在每次外部命令调用后获取终端大小,因此我们可能希望在初始化变量后将其关闭:
shopt -u checkwinsize
如果由于某种原因,我们仍想使用$LINES
,并$COLUMNS
在我们的脚本环境,我们可以配置猛砸这些变量导出到环境:
trap 'export LINES COLUMNS' DEBUG
BashDEBUG
陷阱在提示符下输入每个命令之前执行,因此我们可以使用它来导出这些变量。通过使用每个命令重新导出它们,我们可以确保在终端大小更改时环境变量保持最新状态。将此行与上面显示的选项一起添加到.bashrccheckwinsize
中。它适用于个人脚本,但是我不建议在将要共享的任何脚本中使用这些变量。