'While' and 'until' loops
You may wish to execute a sequence of commands for a variable
number of times while a certain specified condition holds. The
if statement allows a single test to be carried out;
multiple tests can be carried out using while . The
syntax is
while command1
do command2
done
indicating that command1 is executed repeatedly. Each
time its exit status is checked, and if the exit status is zero,
command2 is executed.
Note that the exit status of true is always
0 .
As soon as command1 yields a non-zero exit status, the
while loop ceases immediately. As a simple example of
a while loop, the following will display tick on your
terminal repeatedly once a second:
$ while true
> do
> echo tick
> sleep 1
> done
Don't forget to press ctrl-C to stop it!
Worked example
Use a while loop to print out the 'twelve times
table':
1 x 12 = 12
2 x 12 = 24
...
12 x 12 = 144
Solution: Use a while loop and
bc to do the calculations. Set a variable
i to start at 1 and then become in turn
2 , 3 , up to 12 . While the
value of i is less than or equal to 12
evaluate $i * 12 using bc ,
storing the answer in variable result , display the
line of the table, and add one to i using
bc again.
$ i=1
$ while [ $i -le 12 ]
> do
> result=$( echo "$i * 12" | bc
)
> echo "$i x 12 = $result"
> i=$( echo "$i + 1" | bc )
> done
Similar to while is until ; the syntax
is the same as while , but instead of the condition
that command1 must succeed for the loop to continue to
execute, command1 must fail, and the loop finishes when
the condition gives non-zero exit status. So
until command1
do command2
done
indicates that command1 is executed repeatedly. Each
time its exit status is checked, and if the exit status is
not zero, command2 is executed. As soon as
command1 yields a zero exit status, the until
loop ceases.
Worked example
Write a script to repeatedly request names of files to be
displayed, until you type in QUIT to stop.
Solution: Use an until loop
repeatedly to read in the name of a file, and then (after having
checked that it can be read) displayed it. Note that we commence by
setting the value of the filename, stored in the variable
FILENAME , to "" (i.e. the null string).
This is advisable, just in case the user running the script has
already set FILENAME to QUIT - in which
case the script would stop immediately it had begun to run. This
may appear highly unlikely, but you should always err on the side
of caution.
FILENAME="" # Initialise FILENAME
until [ "$FILENAME" = "QUIT" ] # Finish when value is QUIT
do
echo "Name of file to print (or QUIT to finish):"
read FILENAME # Read in FILENAME
if [ -r "$FILENAME" ] # If it's readable ...
then lp "$FILENAME" # print it
fi
done
Two other commands are provided for use in while ,
until and for loops. The first one is
break , which is a method of breaking out of a loop. If
a break command is encountered the immediately
enclosing loop will terminate immediately. The other command is
continue ; unlike break , instead of
completely leaving the loop, control passes back to the beginning
of the loop.
Worked example
A file called core is sometimes created when a
program 'crashes' - it is very big, and you will often need to
delete it. Write a script to check once a minute to see whether you
have created a file called core in your home
directory, and to terminate with a message on your terminal warning
you of this fact.
Solution: There are several ways of approaching
this, and we present two possible solutions. Both use loops, check
the existence of the file core using the
test command, and sleep for 60 seconds
between tests. The first uses until :
until [ -f $HOME/core ] # Stop when $HOME/core exists
do
sleep 60 # Wait one minute
done
echo core file created # Notify the user
The second solution involves looping forever. Within each loop
it does the test and, if this detects the file, it
uses break to leave the loop:
while true # Forever ...
do
sleep 60 # Wait one minute ...
if [ -f $HOME/core ] # If $HOME/core exists ...
then break # leave the loop
fi
done
echo core file created # Notify the user
Try running one of these scripts in the background. You can
create a file core yourself, using touch ,
say, to check that it does indeed work:
$ touch core
Instead of writing a shell script, you might have considered
crontab for this task.
|