Shell脚本获取终端尺寸

在编写 shell 脚本时经常使用的函数可以封闭到一个脚本中,然后其他脚本使用 source 命令直接调用即可,这样不仅有利于新脚本的开发,更有利于维护。但是今天在编写新的脚本 chaos.sh 时调用了我之前在diary.sh中调用过的菜单脚本,然而却出现错误。一直提示" stty: 标准输入: 对设备不适当的 ioctl 操作" 。

造成这个问题的原因是:使用 Neovim 内置命令运行脚本时并没有真正在一个终端中运行,而菜单脚本使用tty获取终端的尺寸,此时没有可用的tty, 因此出现报错。

一个更健壮的获取终端尺寸的方法(在非终端环境下,如 Neovim :!sh ./chaos.sh 等也不会报错),是使用tput, 这是一具兼容度最好的方案。具体原因是

  • tput 会尝试从环境变量或terminfo 中获取尺寸
  • 在非终端环境下返回空或错误,可用||提供默认值
  • 不会像stty size 那样报错

一般情况下,使用stty sizetput会获得相同的结果,为了确保与之前脚本的兼容性,修改获取尺寸函数为:

~/.Share_Fun/Share_Fun_Menu.sh
1
2
3
4
5
6
7
8
9
10
11
12
# 列表程序
DY_SET_SIZE(){
if [ -t 0 ]; then
TTY_H=$(stty size|awk '{print $1}')
TTY_W=$(stty size|awk '{print $2}')
else
TTY_H=$(tput lines 2>/dev/null) || TTY_H=37
TTY_W=$(tput cols 2>/dev/null) || TTY_W=147
fi
let TTY_H-=2
}
DY_SET_SIZE

通过[ -t 0 ]来判断运行程序时是否在终端,若在终端仍然使用stty size获取终端尺寸,否则使用tput获取。这样重新定义获取尺寸函数后,问题彻底解决。