9.2. The while loop

9.2.1. What is it?

The while construct allows for repetitive execution of a list of commands, as long as the command controlling the while loop executes successfully (exit status of zero). The syntax is:

while CONTROL-COMMAND; do CONSEQUENT-COMMANDS; done

CONTROL-COMMAND can be any command(s) that can exit with a success or failure status. The CONSEQUENT-COMMANDS can be any program, script or shell construct.

As soon as the CONTROL-COMMAND fails, the loop exits. In a script, the command following the done statement is executed.

The return status is the exit status of the last CONSEQUENT-COMMANDS command, or zero if none was executed.

9.2.2. Examples

9.2.2.1. Simple example using while

Here is an example for the impatient:


#!/bin/bash # This script opens 4 terminal windows. i="0" while [ $i -lt 4 ] do xterm & i=$[$i+1] done 

9.2.2.2. Nested while loops

The example below was written to copy pictures that are made with a webcam to a web directory. Every five minutes a picture is taken. Every hour, a new directory is created, holding the images for that hour. Every day, a new directory is created containing 24 subdirectories. The script runs in the background.


#!/bin/bash # This script copies files from my homedirectory into the webserver directory. # (use scp and SSH keys for a remote directory) # A new directory is created every hour. PICSDIR=/home/carol/pics WEBDIR=/var/www/carol/webcam while true; do DATE=`date +%Y%m%d` HOUR=`date +%H` mkdir $WEBDIR/"$DATE" while [ $HOUR -ne "00" ]; do DESTDIR=$WEBDIR/"$DATE"/"$HOUR" mkdir "$DESTDIR" mv $PICDIR/*.jpg "$DESTDIR"/ sleep 3600 HOUR=`date +%H` done done 

Note the use of the true statement. This means: continue execution until we are forcibly interrupted (with kill or Ctrl+C).

This small script can be used for simulation testing; it generates files:


#!/bin/bash # This generates a file every 5 minutes while true; do touch pic-`date +%s`.jpg sleep 300 done 

Note the use of the date command to generate all kinds of file and directory names. See the man page for more.

NoteUse the system
 

The previous example is for the sake of demonstration. Regular checks can easily be achieved using the system's cron facility. Do not forget to redirect output and errors when using scripts that are executed from your crontab!

9.2.2.3. Using keyboard input to control the while loop

This script can be interrupted by the user when a Ctrl+C sequence is entered:


#!/bin/bash # This script provides wisdom FORTUNE=/usr/games/fortune while true; do echo "On which topic do you want advice?" cat << topics politics startrek kernelnewbies sports bofh-excuses magic love literature drugs education topics echo echo -n "Make your choice: " read topic echo echo "Free advice on the topic of $topic: " echo $FORTUNE $topic echo done 

A here document is used to present the user with possible choices. And again, the true test repeats the commands from the CONSEQUENT-COMMANDS list over and over again.

9.2.2.4. Calculating an average

This script calculates the average of user input, which is tested before it is processed: if input is not within range, a message is printed. If q is pressed, the loop exits:


#!/bin/bash # Calculate the average of a series of numbers. SCORE="0" AVERAGE="0" SUM="0" NUM="0" while true; do echo -n "Enter your score [0-100%] ('q' for quit): "; read SCORE; if (("$SCORE" < "0")) || (("$SCORE" > "100")); then echo "Be serious. Common, try again: " elif [ "$SCORE" == "q" ]; then echo "Average rating: $AVERAGE%." break else SUM=$[$SUM + $SCORE] NUM=$[$NUM + 1] AVERAGE=$[$SUM / $NUM] fi done echo "Exiting." 

Note how the variables in the last lines are left unquoted in order to do arithmetic.