使用bash脚本获取控制台宽度


15

我遇到一个试图通过使用脚本来获取终端大小的问题。通常,我会tput cols在控制台内使用该命令,但是我希望能够通过严格使用脚本来完成此功能。

到目前为止,我能够检测正在运行的控制台并获取其文件路径。但是,我正在努力使用此信息来获取控制台的宽度。我尝试使用命令tput,但是我对Linux /脚本是相当陌生的,因此并不真正知道该怎么做。

这样做的原因是我希望能够设置一个cron条目,每隔一段时间就通知控制台其宽度/列。

到目前为止,这是我的代码:

tty.sh

#!/bin/bash

#Get PID of terminal
#terminal.txt holds most recent PID of console in use
value=$(</home/test/Documents/terminal.txt)

#Get tty using the PID from terminal.txt
TERMINAL="$(ps h -p $value -o tty)"
echo $TERMINAL

#Use tty to get full filepath for terminal in use
TERMINALPATH=/dev/$TERMINAL
echo $TERMINALPATH

COLUMNS=$(/home/test/Documents/get_columns.sh)
echo $COLUMNS

get_columns.sh

#!/usr/bin/env bash
echo $(/usr/bin/tput cols)

TERMINAL&的正常输出TERMINALPATH是and ,例如&pts/terminalnumber/dev/pts/terminalnumberpts/0/dev/pts/0



@phk我认为这没有帮助。那里的问题是如何告诉tty驱动程序列/行的实际值。这是从tty驱动程序确定它们。
roaima '16

我认为cron工作没有控制终端。
TMN

Answers:


18

tput命令是一个很好的工具,但是很遗憾,它无法检索任意选择的终端的实际设置。

这样做的原因是它读取stdout的端子特性,这也是它写答案的地方。因此,当您尝试捕获输出时,tput cols也已删除了其信息源。

幸运的是,stty读取stdin而不是stdout来确定终端的特性,因此这是您可以检索所需大小信息的方式:

terminal=/dev/pts/1
columns=$(stty -a <"$terminal" | grep -Po '(?<=columns )\d+')
rows=$(stty -a <"$terminal" | grep -Po '(?<=rows )\d+')

顺便说一句,将其写为不必要地麻烦echo $(/usr/bin/tput cols)

对于任何构造,echo $(some_command)您都在运行some_command并捕获其输出,然后将其传递echo到输出。在几乎每种情况下,您都可以想象您也可以运行some_command并直接输出其输出。它更有效,也更容易阅读。


其中执行/版本tput/ nurses?Mine(ncurses 6.0.20160625)如果无法在stdout上执行TIOCGWINSZ,则在stderr上执行。cols=$(tput cols)cols=$(tput cols 2<> /dev/ttyx) 工作正常。
斯特凡Chazelas

@StéphaneChazelas我最初从Debian“ sid”安装了5.9 + 20140913-1 + b1。只是现在寻找更新的版本。
roaima

1
ncurses 5.7.20100313在这里也可以使用。您肯定cols=$(tput cols 2<> /dev/tty1)对您不利吗?
斯特凡Chazelas

@StéphaneChazelas令人着迷。您是对的:如果我将stdout从终端移开,则会tput colsstderr中读取。我现在需要弄清楚如何重写我的答案...
roaima

1
我会使用stty size <"$terminal" | read rows columns而不是尝试解析stty -a
Random832 '16

13

tput colstput lines从其stdout上的终端设备查询终端的大小(从终端设备驱动程序,而不是终端本身),如果stdout不是终端设备(如在cols=$(tput cols)那儿是管道,则从stderr)。

因此,要从任意终端设备检索值,您需要在stderr上打开该设备tput

{ cols=$(tput cols) rows=$(tput lines); } 2< "$TERMINALPATH"

(此处以只读模式打开,因此tput不会在此处输出错误消息)。

或者,您可以使用stty sizestty在stdin上查询终端:

read rows cols < <(stty size < "$TERMINALPATH")

这些都不是标准的,因此可能(并且实际上将)不适用于所有系统。不过,它应该可以移植到GNU / Linux系统中。

stty size向POSIX请求添加或其他方法来查询终端大小,但是讨论似乎没有进行。


8

该脚本:

#!/bin/bash

echo "The number of columns are $COLUMNS"
echo "The number of lines are $LINES"

在这里工作绝对没有更多.....

为什么要用数据设置环境变量?栏= $(/ home / test / Documents / get_columns.sh)

您是否尝试从其他脚本或tty获取列和行?是吗 对于我来说仍然很奇怪,因为您正在为本地脚本设置co​​lumns环境变量。


这无助于检索cron特定终端的OP 作业中的值。
roaima '16

1
安吗 什么?现在我更困惑了,cronjobs脚本怎么能有宽度?它们实际上不在终端中运行。
Luciano Andress Martini 2016年

我知道。该cron工作查询其特征的特定终端。(我不完全确定为什么需要这样做,但这就是OP想要的。)
roaima

@LucianoAndressMartini $ COLUMNS和$ LINES是bash变量,在破折号和豪华模式中不起作用(例如)
ingroxd

Tks。我真的知道,但是我的脚本是/ bin / bash的hashbang,我认为应该知道您应该使用它。如果您使用的是不带bash的unix,也许我的答案不适合您。
路西亚诺·安妮丝·马丁尼

1

我的回答与Roaima的回答不同,因为它是动态的。他/她的答案为您提供了创建时终端的大小。例如,如果使用的是平铺窗口管理器(如i3或bspwm),则希望具有终端的当前宽度。因此,我使用coreutils包中的ssty:

#!/bin/bash
stty size | awk '{print $2}'

Luciano的解决方案在xterm和xfce4-terminal上完美运行。我不知道是否所有终端都设置了$ COLUMNS变量。


再没有我的回答那么动态了。两者都会在您运行命令时为您提供终端大小。
roaima '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.