Main index

Introducing UNIX and Linux


Introduction to shells

Overview
Why do we need a shell?
Shell syntax
      Types of shell command
      Simple commands
      Pipelines
      Grouping commands
      Exit status
      List commands
Arithmetic
      Operators and functions
Making decisions
      The 'test' statement
            Operators used by 'test'
      The 'if' statement
Loops
      'For' loops
      'While' and 'until' loops
Searching for files
      Arguments to 'find'
Formatted output
      Arguments to 'printf'
Passing information to scripts
      Scripts with arguments
      Parameter expansion
Summary
Exercises

'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.


Copyright © 2002 Mike Joy, Stephen Jarvis and Michael Luck