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