How to create dialog boxes in an interactive shell script

When you install new software in the terminal environment, you may often see informative dialog boxes popping up, accepting your input. The type of dialog boxes ranges from simple yes/no dialog to input box, password box, checklist, menu, and so on. The advantage of using such user-friendly dialog boxes is obvious as they can guide you to enter necessary information in an intuitive fashion.

When you write an interactive shell script, you can actually use such dialog boxes to take user's input. Pre-installed on all modern Linux distributions, a program called whiptail can streamline the process of creating terminal-based dialogs and message boxes inside a shell script, similar to how Zenity or Xdialog codes a GUI for scripts.

In this tutorial, I describe how to create user-friendly dialog boxes in a shell script by using whiptail. I also show Bash code snippets of various dialog boxes supported by whiptail.

Create a Message Box

A message box shows any arbitrary text message with a confirmation button to continue.

whiptail --title "<message box title>" --msgbox "<text to show>" <height> <width>

Example:

#!/bin/bash
whiptail --title "Test Message Box" --msgbox "Create a message box with whiptail. Choose Ok to continue." 10 60

Create a Yes/No Box

One common user input is Yes or No. This is when a Yes/No dialog box can be used.

whiptail --title "<dialog box title>" --yesno "<text to show>" <height> <width>

Example:

#!/bin/bash
if (whiptail --title "Test Yes/No Box" --yesno "Choose between Yes and No." 10 60) then
    echo "You chose Yes. Exit status was $?."
else
    echo "You chose No. Exit status was $?."
fi

Optionally, you can customize the text for Yes and No buttons with "--yes-button" and "--no-button" options.

Example:

#!/bin/bash
if (whiptail --title "Test Yes/No Box" --yes-button "Skittles" --no-button "M&M's"  --yesno "Which do you like better?" 10 60) then
    echo "You chose Skittles Exit status was $?."
else
    echo "You chose M&M's. Exit status was $?."
fi

Create a Free-form Input Box

If you want to take any arbitrary text input from a user, you can use an input box.

whiptail --title "<input box title>" --inputbox "<text to show>" <height> <width> <default-text>

Example:

#!/bin/bash
PET=$(whiptail --title "Test Free-form Input Box" --inputbox "What is your pet's name?" 10 60 Wigglebutt 3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus = 0 ]; then
    echo "Your pet name is:" $PET
else
    echo "You chose Cancel."
fi

Create a Password Box

A password box is useful when you want to take a sensitive input from a user.

whiptail --title "<password box title>" --passwordbox "<text to show>" <height> <width>

Example:

#!/bin/bash
PASSWORD=$(whiptail --title "Test Password Box" --passwordbox "Enter your password and choose Ok to continue." 10 60 3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus = 0 ]; then
    echo "Your password is:" $PASSWORD
else
    echo "You chose Cancel."
fi

Create a Menu Box

When you want to ask a user to choose one among any arbitrary number of choices, you can use a menu box.

whiptail --title "<menu title>" --menu "<text to show>" <height> <width> <menu height> [ <tag> <item> ] . . .

Example:

#!/bin/bash
OPTION=$(whiptail --title "Test Menu Dialog" --menu "Choose your option" 15 60 4 \
"1" "Grilled Spicy Sausage" \
"2" "Grilled Halloumi Cheese" \
"3" "Charcoaled Chicken Wings" \
"4" "Fried Aubergine"  3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus = 0 ]; then
    echo "Your chosen option:" $OPTION
else
    echo "You chose Cancel."
fi

Create a Radiolist Dialog

A radiolist box is similar to a menu box in the sense that you can choose only option among a list of available options. Unlike a menu box, however, you can indicate which option is selected by default by specifying its status.

whiptail --title "<radiolist title>" --radiolist "<text to show>" <height> <width> <list height> [ <tag> <item> <status> ] . . .

Example:

#!/bin/bash
DISTROS=$(whiptail --title "Test Checklist Dialog" --radiolist \
"What is the Linux distro of your choice?" 15 60 4 \
"debian" "Venerable Debian" ON \
"ubuntu" "Popular Ubuntu" OFF \
"centos" "Stable CentOS" OFF \
"mint" "Rising Star Mint" OFF 3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus = 0 ]; then
    echo "The chosen distro is:" $DISTROS
else
    echo "You chose Cancel."
fi

Create a Checklist Dialog

A checklist dialog is useful when you want to ask a user to choose more than one option among a list of options, which is in contrast to a radiolist box which allows only one selection.

whiptail --title "<checklist title>" --checklist "<text to show>" <height> <width> <list height> [ <tag> <item> <status> ] . . .

Example:

#!/bin/bash
DISTROS=$(whiptail --title "Test Checklist Dialog" --checklist \
"Choose preferred Linux distros" 15 60 4 \
"debian" "Venerable Debian" ON \
"ubuntu" "Popular Ubuntu" OFF \
"centos" "Stable CentOS" ON \
"mint" "Rising Star Mint" OFF 3>&1 1>&2 2>&3)

exitstatus=$?
if [ $exitstatus = 0 ]; then
    echo "Your favorite distros are:" $DISTROS
else
    echo "You chose Cancel."
fi

Create a Progress Bar

Another user-friendly dialog box is a progress bar. whiptail reads from standard input a percentage number (0 to 100) and displays a meter inside a gauge box accordingly.

whiptail --gauge "<test to show>" <height> <width> <inital percent>
#!/bin/bash
{
    for ((i = 0 ; i <= 100 ; i+=20)); do
        sleep 1
        echo $i
    done
} | whiptail --gauge "Please wait while installing" 6 60 0

By now, you must see how easy it is to create useful dialog boxes in an interactive shell script. Next time you need to write a shell script for someone, why don't you try whiptail and impress him or her? :-)

Subscribe to Xmodulo

Do you want to receive Linux FAQs, detailed tutorials and tips published at Xmodulo? Enter your email address below, and we will deliver our Linux posts straight to your email box, for free. Delivery powered by Google Feedburner.


Support Xmodulo

Did you find this tutorial helpful? Then please be generous and support Xmodulo!

The following two tabs change content below.
Dan Nanni is the founder and also a regular contributor of Xmodulo.com. He is a Linux/FOSS enthusiast who loves to get his hands dirty with his Linux box. He likes to procrastinate when he is supposed to be busy and productive. When he is otherwise free, he likes to watch movies and shop for the coolest gadgets.

16 thoughts on “How to create dialog boxes in an interactive shell script

  1. Hmm. If I use "dialog", it uses the stdout and leaves the dialog box cluttering the screen after it exits, so it loses previous output off the top of the screen.

    a=$(dialog --title "test" --stdout --inputbox "Enter text" 5 40); echo $a

    "Whiptail" seems better in that it does some fancy footwork with stdout and stderr to allow the removal of the dialog box afterward, but that apparently means that you can't simply redirect the output into an environment variable unless, it seems, that you add in all that redirection mumbo-jumbo as a workaround:

    a=$(whiptail --title "Test" --inputbox "Enter text" 5 40 3>&1 1>&2 2>&3); echo $a

    Messy. I'd hope there's a better way.

  2. A few silly things here I have to point out.
    What's with the pointless subshell in the if? There's no point in forking a subshell just to fork and run yet another command. Lose the parenthesis. if whiptail ...; then
    Don't use uppercase variable names as one risks overriding special shell variables and environment variables. Plus they look ugly.
    Capturing the exit status and using a [ command to test if the previous command succeeded or not is a pointless and silly step. Just test the command in the first place.
    Leaving $PET unquoted will potentially will modify the content before it gets passed to echo; it should be inside the quotes too: echo "Your pet name is: $PET". Or better yet, use printf.

    #!/usr/bin/env bash
    if pet=$(whiptail ...); then
    printf "Your pet's name is: %s\n" "$pet"
    else
    printf "You canceled.\n"
    fi

  3. Thanks for the tutorial. Would love to try it out. Maybe it would be a good idea to begin by mentioning why it's preferable to dialog and how to get it (not in the default repos for CentOS6 or in MacPorts, for instance)?

  4. The RadioList example text contains HTML character entities which, nautrally, don't make it easy to copy-n-paste the code. :)

    Still, straight forward examples of using 'whiptail' which I didn't know about -- just 'dialog'. Thanks!

  5. If you use Wiptail for a "front-end" I recommend that you redirect any screen output to a log file so that if there are any errors you can check those file(s). For example progress bar

    #!/bin/bash
    {
    wget -O - http://example.com/download.file > /var/log/wget.log 2&>1
    } | whiptail --gauge "Please wait while downloading download.file" 6 60 0

    Check /var/log/wget.log to see any errors.
    I do recommend different (log) files for different steps to make it easier to find errors. You might want to make own sub-directory also.
    Hope this helps!

Leave a comment

Your email address will not be published. Required fields are marked *