Shell中的TUI与GUI

简介

在 Shell 中创建 TUI 格外方便且简单。这可以说是一大优势了。

Dialog

dialog是基于ncurses库的,在Linux的命令行下实现TUI界面的工具。

安装

1
2
3
4
5
# Debian
apt install dialog

# RHEL
yum install dialog

用法

dialog的语法为:
dialog [选项] --title "标题" --控件类型 "描述" 高 宽 控件属性

高 宽0 0时,进行自动大小调整。
高 宽1 1时,进行最大化。
列表高度菜单高度0时,进行自动大小调整。

在窗口中,选择OKYesdialog返回0,选择CancelNodialog返回1,按下ESCdialog返回255

dialog的图形界面通过标准输出流打印,选择与输入结果通过标准错误流打印,要将结果保存到变量,要么使用2> 文件进行过渡,要么通过3>&1 1>&2 2>&3临时交换标准输出与标准错误,对于列表变量,还要通过($变量名)转换为数组变量。

选项

选项有以下几项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--stderr                # 以标准错误方式输出
--stdout # 以标准输出方式输出
--output-separator "${IFS}" # 指定输出的分隔符,默认为换行(对列表来说是空格)
--clear # 进行清屏操作。在窗口显示结束后,清除窗口。这个选项只能单独使用
--shadow # 出现阴影效果,这是默认选项
--no-shadow # 禁止阴影出现在每个对话框的底部
--insecure # 使用星号来代表每个字符,用于密码
--no-cancel # 在输入框,菜单,和复选框中,不显示"Cancel"选项
--ok-label "内容" # 覆盖"OK"按钮的内容,换成其他内容
--cancel-label "内容" # 覆盖"Cancel"按钮的内容,换成其他内容
--backtitle "标题" # 指定背景标题字符串,显示在背景顶部
--begin Y X # 指定对话框的左上角锚点在屏幕的上的坐标
--timeout 秒 # 如果用户在指定的时间内没有给出相应动作,就按超时(返回错误代码)处理
--sleep 秒 # 静止指定时间
--default-item "标签" # 设置在一份清单,表格或菜单中的默认项目。通常在框中的第一项是默认

控件

类型 选项 含义
日历框 --calendar "描述" 高 宽 [日 月 年] 提供了一个日历,让用户选择日期,打印到错误输出
时间框 --timebox [--time-format 格式] "描述" 高 宽 提供一个窗口,选择小时,分钟,秒,打印到错误输出
文件选择框 --fselect "目录路径" 高 宽 提供一个路径,让用户选择文件,路径打印到错误输出
进度框 --gauge "描述" 高 宽 起始百分比 类似于pv命令,接受标准输入,按百分比显示输入进度
单选框 --radiolist "描述" 高 宽 菜单高度 "标签1" "内容1" on或off 让用户选择列表中的单个选项,打印选择的标签到错误输出
菜单框 --menu [--no-tags] [--no-items] "描述" 高 宽 菜单高度 "标签1" "内容1"... 让用户选择菜单中的单个选项,打印选择的标签到错误输出
复选框 --checklist [--no-tags] [--no-items] "描述" 高 宽 菜单高度 "标签1" "内容1" on或off... 让用户选择列表中的多个选项,打印空格分隔的标签列表到错误输出
信息框 --infobox "描述" 高 宽 对话框立刻显示消息并继续执行,但并不清除屏幕
输入框 --inputbox "描述" 高 宽 ["初始输入内容"] 允许用户输入文本,将输入内容打印到错误输出
密码框 --passwordbox --insecure "描述" 高 宽 ["初始输入内容"] 类似于输入库,但是不在窗口中显示输入内容
消息框 --msgbox "描述" 高 宽 向用户显示一条消息,同时显示一个OK按钮,用户确认后才会继续操作
文本框 --textbox [--scrollbar] "文件路径" 高 宽 在带有滚动条的文本框中显示一个文件的内容
反文本框 --tailbox "文件路径" 高 宽 从下而上的在文本框中显示一个文件的内容
编辑框 --editbox "文件路径" 高 宽 在窗口中编辑一个文件
是/否框 --yesno [--defaultno] "描述" 高 宽 进行提问,用户可以选择yes或no,yes返回0,no返回1

Whiptail

whiptail是由红帽开发的,基于newt库的全新(1998年)TUI界面工具,相比于dialogwhiptail精简了部分选项,简化了用法,同时又保留了很大程度的兼容。目前大部分发行版制作的TUI工具都基于whiptail

安装

1
2
3
4
5
# Debian
apt install whiptail

# RHEL
yum install newt

用法

whiptail的语法为:
whiptail [选项] --title "标题" --控件类型 "描述" 高 宽 控件属性

高 宽0 0时,进行自动大小调整。
高 宽1 1时,进行最大化。
当控件属性的列表高度菜单高度0时,进行自动大小调整。

在窗口中,选择OKYeswhiptail返回0,选择CancelNowhiptail返回1,按下ESCwhiptail返回255

whiptail的图形界面通过标准输出流打印,选择与输入结果通过标准错误流打印,要将结果保存到变量,要么使用2> 文件进行过渡,要么通过3>&1 1>&2 2>&3临时交换标准输出与标准错误输出,对于列表变量,还要通过($变量名)将其转换为数组变量。

resize命令会打印出whiptailLINESCOLUMNS变量,它们决定着whiptail的窗口大小,可以通过eval $(resize)命令获取这两个变量,并在之后用于设定。

选项

选项有以下几项:

1
2
3
4
5
6
7
8
--seperate-output       # 对于列表,将分隔符从空格转换为换行符
--clear # 进行清屏操作。在窗口显示结束后,清除窗口。这个选项只能单独使用
--nocancel # 在输入框,菜单,和复选框中,不显示"Cancel"选项
--ok-button "内容" # 覆盖"OK"按钮的内容,换成其他内容
--cancel-button "内容" # 覆盖"Cancel"按钮的内容,换成其他内容
--backtitle "标题" # 指定背景标题字符串,显示在背景顶部
--topleft # 窗口从屏幕左上角开始定位,而不是屏幕中央
--default-item "标签" # 设置在一份清单,表格或菜单中的默认项目。通常在框中的第一项是默认

控件

类型 选项 含义
进度框 --gauge "描述" 高 宽 起始百分比 类似于pv命令,接受标准输入,按百分比显示输入进度
单选框 --radiolist "描述" 高 宽 菜单高度 "标签1" "内容1" on或off... 让用户选择列表中的单个选项,打印选择的标签到错误输出
菜单框 --menu [--notags] [--noitems] "描述" 高 宽 菜单高度 "标签1" "内容1"... 让用户选择菜单中的单个选项,打印选择的标签到错误输出
复选框 --checklist [--notags] [--noitems] "描述" 高 宽 菜单高度 "标签1" "内容1" on或off... 让用户选择列表中的多个选项,打印空格分隔的标签列表到错误输出
信息框 --infobox "描述" 高 宽 立刻显示一个消息并退出,然后继续执行,但并不清除屏幕
输入框 --inputbox "描述" 高 宽 ["初始输入内容"] 允许用户输入文本,将输入内容打印到错误输出
密码框 --passwordbox "描述" 高 宽 ["初始输入内容"] 类似于输入框,但是不在窗口中显示输入内容
消息框 --msgbox "描述" 高 宽 向用户显示一条消息,同时显示一个OK按钮,用户确认后才会继续操作
文本框 --textbox [--scrolltext] "文件路径" 高 宽 在带有滚动条的文本框中显示一个文件的内容
是/否框 --yesno [--defaultno] [--yes-button "内容"] [--no-button "内容"] "描述" 高 宽 进行提问,用户可以选择yes或no,yes返回0,no返回1

实例

均以whiptail为例。

二选一

1
2
3
4
5
6
if (whiptail --title "" --yesno "Choose between Yes and No:" 0 0)
then
echo "You chose Yes."
else
echo "You chose No."
fi

获取输入

1
variable=$(whiptail --title "" --inputbox "Variable:" 0 0 3>&1 1>&2 2>&3)

获取密码

1
PASSWORD=$(whiptail --title "Password" --passwordbox "Enter your password:" 0 0 3>&1 1>&2 2>&3)

显示选择菜单

1
2
3
4
5
OPTION=$(whiptail --title "" --menu "Choose your option:" 0 0 0 \
"1" "I am option 1." \
"2" "I am option 2." \
"3" "I am option 3." \
"4" "I am option 4." 3>&1 1>&2 2>&3)

进行单选

1
2
3
4
5
OPTION=$(whiptail --title "" --radiolist "Choose your option:" 0 0 0 \
"1" "I am option 1." \
"2" "I am option 2." \
"3" "I am option 3." \
"4" "I am option 4." 3>&1 1>&2 2>&3)

进行多选

1
2
3
4
5
6
7
8
9
10
OPTIONS=$(whiptail --title "" --checklist \
"What is the Linux distro of your choice?" 0 0 0 \
"1" "I am option 1." on \
"2" "I am option 2." on \
"3" "I am option 3." off \
"4" "I am option 4." off 3>&1 1>&2 2>&3)

OPTIONS_ARRAY=($OPTIONS)
# 或者使用mapfile
mapfile -t -d ' ' OPTIONS_ARRAY <<< "${OPTIONS}"

进度条

1
2
3
4
for i in $(seq 1 100); do
sleep 0.1
echo $i
done | whiptail --title "" --gauge "" 0 0 0

Zenity

zenity是由GNOME团队开发的,通过脚本唤醒GTK下的GUI的工具。

安装

1
2
3
4
5
# Debian
apt install zenity

# RHEL
yum install zenity

用法

zenity的语法为:
zenity [选项] --title "标题" --控件类型 [控件选项]

在窗口中,选择OKYeszenity返回0,选择Cancel关闭窗口zenity返回1

zenity的选择与输入结果通过标准输出流打印,分割符默认为|,要将结果保存到变量,只需要通过变量名=$(zenity ...)即可,对于列表变量,还要通过($变量名)将其转换为数组变量。

选项

选项有以下几项:

1
2
3
4
--window-icon    # 指定图标路径,否则使用默认图标
--width # 指定窗口宽度,否则自动估计宽度
--height # 指定窗口高度,否则自动估计高度
--timeout # 指定窗口显示超时,否则无限时间

控件

类型 选项 含义
进度框 --progress [--text "描述" --percentage 初始值 --auto-close --auto-kill --pulsate --no-cancel] 显示一个进度条,--auto-close在完成时自动关闭,--auto-kill允许点击Cancel强制杀死,--pulsate不显示具体进度,--no-cancel不显示Cancel按钮
输入框 --entry [--text "描述" --entry-text "初始文本" --hide-text] 允许用户输入文本,将输入内容打印到标准输出,--hide-text表示隐藏输入的文字
密码框 --password [--username] 类似于输入框,但是不在窗口中显示输入内容
文本框 --text --filename "打开文件" --editable --checkbox --ok-label "OK按钮内容" --cancel-label "Cancel按钮内容" 显示一个文件内容让用户阅读,--editable启用文本编辑,--checkbox让用户确认阅读
消息框 --info [--text "描述" --no-wrap] 显示普通的信息框,--no-wrap表示文字不换行
警告框 --warning [--text "描述" --no-wrap] 显示带有叹号的警告框,--no-wrap表示文字不换行
错误框 --error [--text "描述" --no-wrap] 显示带有巨大叉号的错误框,--no-wrap表示文字不换行
询问框 --question [--text "描述" --no-wrap --ok-label "OK按钮内容" --cancel-label "Cancel按钮内容"] 显示一个是否对话框,让用户进行选择,是则返回0,否则返回1
选择框 --list --checklist/--radiolist [--separator "分割符" --hide-header] --column "列标题" 列内容 显示一个列表,让用户选择列表中的选项,打印选择的选项内容到标准输出,--radiolist单选框,--checklist多选框,--hide-header隐藏列标题
表单框 --forms --add-entry "条目名" [--add-password "条目名" --add-calendar "条目名" --text "描述" --separator "分割符" --forms-date-format "日期格式"] 显示一个让用户进行填写的表单,收集填写的内容并打印到标准输出
通知框 --notification --text "描述" 显示一条系统通知
日历框 --calendar [--text "描述" --day 初始天 --month 初始月 --year 初始年 --date-format "返回日期格式"] 显示一个日历,让用户选择日期,日期按照指定的格式打印到标准输出
滑动条框 --scale [--text "描述" --value "初始值" --min-value "最小值" --max-value "最大值" --step "步长" --print-partial --hide-value] 显示一个滑动条,让用户选择数值,--print-partial显示小数,--hide-value隐藏数字
取色框 --color-selection [--color "初始颜色" --show-palette] 显示一个取色器,让用户选择一种颜色,--show-palette使用调色板进行选择
文件选择框 --file-selection [--filename 初始文件路径 --multiple --separator "分割符" --directory --save --confirm-overwrite --file-filter "模式"] 让用户选择文件,路径打印到标准输出,--multiple表示启用多选,--separator指定多选分割符,--save表示保存模式,--confirm-overwrite表示覆盖前确认,--file-filter指定文件名的过滤模式

发送通知

除了使用zenity --notification之外,还可以使用Libnotify。
安装Libnotify:

1
2
3
4
5
# Debian
apt install libnotify-bin

# RHEL
yum install libnotify

使用notify-send [选项] "标题" ["内容"]发送系统通知,选项如下:

1
2
3
4
-u|--urgency  # 紧急度,可选low|normal|critical
-t|--expire-time # 显示时间,在某些桌面环境下会被无视
-i|--icon # 使用的图标路径
-c|--category # 通知的类型