BASH: 变量中的对话框输入
BASH: Dialog input in a variable
我正在尝试使用 dialog
命令从输入框中获取用户输入,以在 bash 脚本中创建目录。目前我有以下代码:
rm -f ans.txt
dialog --title "Create Directory" --inputbox "Enter the directory name:" 8 40 2>ans.txt
val=$(<ans.txt)
mkdir $val
它可以工作,但是它需要创建(和删除)一个临时文件。我可以将来自 dialog
的用户输入直接存储到 $val
中而不使用临时文件吗?
基本上,您将使用命令替换将命令的输出获取到变量中。像这样:
date=$(date)
将 date
命令的输出写入变量 $date
.
但是如果我们尝试使用对话框 dialog
命令进行相同操作:
user_input=$(dialog --title "Create Directory" --inputbox "Enter the directory name:" 8 40)
我们得到一个空屏幕!为什么会这样?
解释:
dialog
在 stderr 上输出用户输入,因为 ncurses 已经使用 stdout 来更新屏幕。如果不使用输出重定向,命令替换会将命令的标准输出 return 放入变量中——这意味着 ncurses 的输出不会打印在屏幕上。但是,如果您键入某些内容(键入时您看不到任何内容):
test<enter>
文本 test
将出现在屏幕上。发生这种情况是因为它将被写入 stderr,而 stderr 仍然指向当前终端。
注意: 您可能希望 $user_input
中的 ncurses 输出,但 $user_input
在命令后为空。我认为发生这种情况是因为 dialog
将检查它的输出是否要发送到 tty,否则不会输出任何内容。 (尚未验证)
解法:
我们可以使用 i/o 重新路由交换 stderr 和 stdout。我们会将 stderr 转换为 stdout 并将用户输入写入变量,但另一方面将 stdout 转换为 stderr,这将使 ncurses 输出到屏幕:
3>&1 1>&2 2>&3 3>&-
简而言之:3>&1
打开一个指向 stdout 的新文件描述符,1>&2
将 stdout 重定向到 stderr,2>&3
将 stderr 指向 stdout,3>&-
删除命令执行后的文件描述符 3
。
这给了我们最后的命令:
user_input=$(\
dialog --title "Create Directory" \
--inputbox "Enter the directory name:" 8 40 \
3>&1 1>&2 2>&3 3>&- \
)
mkdir "$user_input"
请注意,Zenity 是一个 GUI 替代品。
如果您正在寻找文本界面,fzf 非常好。您可以轻松地重定向其输出:
var=$(print -l folder/* | fzf)
如果您只想读取用户输入:
var=$(echo '' | fzf --print-query)
这是 zsh 语法,我想 bash 用户会很容易地翻译它。
此外,fzf 与 tmux 交互良好。
我正在尝试使用 dialog
命令从输入框中获取用户输入,以在 bash 脚本中创建目录。目前我有以下代码:
rm -f ans.txt
dialog --title "Create Directory" --inputbox "Enter the directory name:" 8 40 2>ans.txt
val=$(<ans.txt)
mkdir $val
它可以工作,但是它需要创建(和删除)一个临时文件。我可以将来自 dialog
的用户输入直接存储到 $val
中而不使用临时文件吗?
基本上,您将使用命令替换将命令的输出获取到变量中。像这样:
date=$(date)
将 date
命令的输出写入变量 $date
.
但是如果我们尝试使用对话框 dialog
命令进行相同操作:
user_input=$(dialog --title "Create Directory" --inputbox "Enter the directory name:" 8 40)
我们得到一个空屏幕!为什么会这样?
解释:
dialog
在 stderr 上输出用户输入,因为 ncurses 已经使用 stdout 来更新屏幕。如果不使用输出重定向,命令替换会将命令的标准输出 return 放入变量中——这意味着 ncurses 的输出不会打印在屏幕上。但是,如果您键入某些内容(键入时您看不到任何内容):
test<enter>
文本 test
将出现在屏幕上。发生这种情况是因为它将被写入 stderr,而 stderr 仍然指向当前终端。
注意: 您可能希望 $user_input
中的 ncurses 输出,但 $user_input
在命令后为空。我认为发生这种情况是因为 dialog
将检查它的输出是否要发送到 tty,否则不会输出任何内容。 (尚未验证)
解法:
我们可以使用 i/o 重新路由交换 stderr 和 stdout。我们会将 stderr 转换为 stdout 并将用户输入写入变量,但另一方面将 stdout 转换为 stderr,这将使 ncurses 输出到屏幕:
3>&1 1>&2 2>&3 3>&-
简而言之:3>&1
打开一个指向 stdout 的新文件描述符,1>&2
将 stdout 重定向到 stderr,2>&3
将 stderr 指向 stdout,3>&-
删除命令执行后的文件描述符 3
。
这给了我们最后的命令:
user_input=$(\
dialog --title "Create Directory" \
--inputbox "Enter the directory name:" 8 40 \
3>&1 1>&2 2>&3 3>&- \
)
mkdir "$user_input"
请注意,Zenity 是一个 GUI 替代品。
如果您正在寻找文本界面,fzf 非常好。您可以轻松地重定向其输出:
var=$(print -l folder/* | fzf)
如果您只想读取用户输入:
var=$(echo '' | fzf --print-query)
这是 zsh 语法,我想 bash 用户会很容易地翻译它。
此外,fzf 与 tmux 交互良好。