Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BASH: Dialog input in a variable

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?

like image 498
Ali Sajid Avatar asked Mar 23 '15 23:03

Ali Sajid


2 Answers

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"
like image 146
hek2mgl Avatar answered Sep 28 '22 14:09

hek2mgl


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.

like image 20
chimay Avatar answered Sep 28 '22 14:09

chimay