I am trying to get user input from the inputbox using the dialog
command to create a directory in a bash script. Currently I have the following code:
rm -f ans.txt
dialog --title "Create Directory" --inputbox "Enter the directory name:" 8 40 2>ans.txt
val=$(<ans.txt)
mkdir $val
It works, however it requires the creation (and deletion) of a temporary file. Can I store the user input from dialog
directly into $val
without using a temporary file?
Basically you will use command substitution to obtain the output of a command into a variable. Like this:
date=$(date)
which writes the output of the date
command to the variable $date
.
But if we try the same with the dialog dialog
command:
user_input=$(dialog --title "Create Directory" --inputbox "Enter the directory name:" 8 40)
we get an empty screen! Why does this happen?
Explanation:
dialog
outputs the user input on stderr, since stdout will already being used by ncurses to update the screen. Without output redirection being used, the command substitution will return the command's stdout into the variable - meaning the output of ncurses will not get printed on screen. However if you type something (you can't see anything while typing):
test<enter>
The text test
will appear on screen. This happens because it will been written to stderr and stderr still points to the current terminal.
Note: You might expect the ncurses output in $user_input
but $user_input
is empty after the command. I assume that this happens because dialog
will check if it's output is going to a tty and it won't output anything otherwise. (Haven't verfied that)
Solution:
We can exchange stderr and stdout using i/o rerouting. We will turn stderr into stdout and write the user input to the variable but on the other hand turn stdout into stderr which will make ncurses outputting to the screen:
3>&1 1>&2 2>&3 3>&-
In short: 3>&1
opens a new file descriptor which points to stdout, 1>&2
redirects stdout to stderr, 2>&3
points stderr to stdout and 3>&-
deletes the files descriptor 3
after the command has been executed.
This gives us the final command:
user_input=$(\
dialog --title "Create Directory" \
--inputbox "Enter the directory name:" 8 40 \
3>&1 1>&2 2>&3 3>&- \
)
mkdir "$user_input"
Note that Zenity is a GUI alternative.
If you looking for a text interface, fzf is really nice. You can easily redirect its output :
var=$(print -l folder/* | fzf)
If you just want to read user input :
var=$(echo '' | fzf --print-query)
It’s zsh syntax, bash users will translate it easily I suppose.
Also, fzf interacts well with tmux.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With