Issue
61: Strictly On-Line: Linux
Apprentice: Improve Bash Shell Scripts Using
Dialog Posted on Saturday, May 01, 1999
by Mihai
Bisca |
| | The dialog command enables the use of
window boxes in shell scripts to make their use more
interactive.
Shell scripts are text files containing commands for
the shell and are frequently used to handle repetitive
tasks. In order to avoid typing the same commands over
and over again, we put them in a file with a few
modifications, give it execute permission and run it.
To control the program at run-time, an interactive
shell script is needed. For this case, the dialog
command offers an easy way to draw text-mode colored
windows. These windows can contain text boxes, message
boxes or different kinds of menus. There are even ways
of using input from the user to modify the script
behaviour.
The current version of the dialog program is
cdialog-0.9 and can be freely downloaded from Sunsite's
/pub/Linux/utils/shell directory. Dialog uses the
ncurses library, so it too must be installed. Some Linux
distributions (i.e., Slackware) include the dialog
program because of utilities which rely on it
(setup, pkgtool). By the way, these
utilities are great examples of using dialog.
Let's examine the dialog version of the most popular
example program around. With your favorite text editor,
create a file named hello containing these lines:
#!/bin/sh
# First shell script with "dialog"
dialog --title "Dialog message box"
--msgbox "
Hello world !" 6 25
The first line of this file identifies it as a
shell script for the ``sh'' shell. Every shell script
must start with the characters ``#!'' followed by the
name (and path) of the shell to execute. For example, we
could have written this line as #!/bin/bash.
The next line is just a comment, like any line starting
with ``#'' other than the first line in the file. Then
comes the dialog command, which will draw a message box
6 lines high and 25 columns wide on the screen,
containing the title ``Dialog message box'' and the
message ``Hello world !''. The message box has an OK
button and when it is selected, the script will end.
Notice the general format of the --msgbox
option:
--msgbox
After writing and saving this file, type:
chmod a+x hello
="./2460f1.gif"
Figure 1. Screenshot of a Dialog
Box
The resulting screen is shown in Figure 1. This
example is so simple it could have been produced with
just one command at the shell prompt. However, things
get more complicated when user input is needed in a
shell script.
For example, to list the contents of a directory, use
dialog as shown in Listing
1. This introduces two new dialog boxes: an
input and a text box. The input box has the general
format:
--inputbox
In Listing 1, the default value displayed in the
input box is obtained by running the command pwd
which returns the present working directory. Whenever a
command is enclosed in reverse quotes, bash replaces it
with its standard output.
Of course, this default value can be changed at
runtime using the backspace key to delete and regular
letter keys to write. The final value is printed by
dialog on STDERR. In order to use it from the shell
script, it must first be redirected to a file. Do this
with the redirection:
2>/tmp/dialog.ans
The next line is necessary in case the user
decides to select the Cancel button in the input box.
When that happens, the exit status of the dialog command
will be 1. Bash keeps the exit status of the last
executed command in the variable $?, so if this
is 1, the shell script will stop after clearing the
screen.
If $? is 0 (the user clicked the OK button),
the answer file is read to set the variable ANS. Again,
reverse quoting proves useful. Another method of doing
this is to use:
ANS=$(cat /tmp/dialog.ans)
The contents of the chosen directory are output to
the same file used before. This can be done safely,
because the > operator overwrites the previous
contents of this file.
All is now set for the next dialog command, which
generates the text box to display the contents of a text
file. It has the general format:
--textbox
The text box allows navigating with the arrow keys
or home/end/pgup/pgdown keys and even has simple
searching facilities. Typing / while the text box is
displayed causes another window to appear, which prompts
the user for a string to be searched forward in the
file. Typing ? performs reverse searching, just as for
the less pager. The first line containing the
string is displayed at the top of the text box.
The experienced programmer might complain about an
obvious flaw in this shell script. What if the directory
name is wrong? The shell script will not complain, but
will show an empty text box since there are no files in
a nonexistent directory. To solve this problem, a check
is made to see if the specified directory exists.
Actually, the ls command returns an exit status
of 0 if the directory exists, and 1 if it doesn't. Thus,
the script can be modified by adding these lines:
ls -al $ANS > /tmp/dialog.ans 2>/dev/null
if [ $? = 1 ]; then
clear
echo no such directory
exit 1
fi
First, the ls line is changed, redirecting
standard error to /dev/null. This means no error
messages from ls will appear on the screen. Then, if the
exit status ($?) is 1, the script will exit
with an error message.
This script can be made even more useful by allowing
the user to examine more directories before the script
exits. (See Listing
2.) A few changes have been made. First, the
entire script has been included in a while-do
loop which is always true. This allows it to run more
than once. Now the only way of exiting the script
(besides typing ctrl-c) is by selecting the Cancel
button in the dialog input box. The second change is the
introduction of a message box which will be displayed
when the ls command returns an exit status of 1. The
command continue deserves a special comment. Its
meaning is to skip the current iteration of the
while loop (i.e., the part which shows the text
box) and start a new one. Thus, after the error message,
the user will again see the input box, prompting for
another directory name.
The menu box is produced by running dialog with the
--menu option with the format:
dialog --menu
tag2 item2...
This option displays a box with two buttons (OK
and Cancel) and a menu consisting of one or more lines.
Each line has a ``tag'' (a number or word) and an
``item'', which is usually text describing the menu
entry. When a user selects an item and then clicks on
the OK button, the corresponding tag is printed on
STDERR. Also, the exit status of dialog is 0 for the OK
button being selected and 1 for the Cancel button.
Menu boxes are useful in that they allow the user to
choose from several fixed alternatives. For example,
when producing a LaTeX document, three steps must be
taken: editing the source file with a word processor,
compiling it with LaTeX and viewing the resulting .dvi
file. It is easy to build a shell script to do these
steps. (See Listing
3 which assumes the text editor is jed,
the .dvi file viewer is dvisvga and both are in
the path.) The complete script is again included in a
``while'' loop for the purpose of making it work more
than one time. The only way to exit this script is by
selecting the ``Cancel'' button in the first menu box.
Otherwise, the user has to choose between three
alternatives:
- Edit a text file.
- Compile a LaTeX file.
- View a .dvi file.
The answer is stored in
the file /tmp/ans and retrieved in the variable
R. If the user chooses to edit a file, a new
dialog box appears. It is an input box and prompts for a
file name. The answer goes into the variable F.
Then the script checks whether the file exists and runs
the command:
jed $F # where $F is the name of the file
If the file does not exist, it is either a new one
or a typing error. To distinguish between these two
possibilities, a yes/no dialog box is provided. The
general format of such a box is:
--yesno
The box has two buttons, YES and NO. The text is
usually a question, which the user answers by selecting
a button. If YES, $? (the exit status of the
dialog command) is 0; if NO, $? is 1.
In Listing 3, if the answer is YES, the text editor
is invoked; if NO, the script returns to the main menu
through the continue command. The other two choices work
in the same way, the only difference being the commands
for processing the file with LaTeX or for viewing the
resulting DVI file:
latex $F
dvisvga $F
Several other dialog boxes are available, such as
the checklist or the radiolist; however, their use is
quite similar to that of the menu box.
I would like to end with an example of the
--guage dialog box. This is used to graphically
display a percentage. The syntax is:
dialog --guage
Once started, the guage box keeps reading percent
values from STDIN until an EOF is reached and changes
the display accordingly. Here is a simple (but not very
useful) guage script:
#!/bin/bash
{ for I in 10 20 30 40 50 60 70 80 90
80 70 60 50 40 30 20 10 0; do
echo $I
sleep 1
done
echo; } | dialog --guage "A guage demo" 6 70 0
Copy this into a file, give it execute permission,
run and enjoy! The first part of the script (included in
braces) is a group command. Every second it sends one of
the listed values to the guage dialog box. The final
echo command is used to terminate the dialog box.
Shell scripting is a convenient way of making your
Linux system ``smarter''. These examples of the most
common dialog boxes should help you make your scripts
more attractive.
Resources
Mihai Bisca is an ophthalmologist who
is crazy about Linux. In 1998 he published the first
Romanian introductory book on Linux. Currently, he is
competing with his three-year-old daughter Andra for
the place at the keyboard. You can reach them at
mbasca@ottonel.pub.ro.
|