BASH: Dialog input in a variable

14,105

Solution 1

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"

Solution 2

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.

Share:
14,105
Ali Sajid
Author by

Ali Sajid

while(alive){ explore() }

Updated on June 18, 2022

Comments

  • Ali Sajid
    Ali Sajid almost 2 years

    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?