Conceptually the for loop should be used to loop through a series of items such as loop through each item in an array or each file in a directory, etc. The while loop should be used as long as a certain condition is true, such as the a counter is less than a maximum value or the ping time to a server is lower than a threshold or forever if you loop while TRUE or while 1.
The until loop is similar to the while loop but with reverse logic. Instead of looping while a condition is true you are assuming the condition is false and looping until it becomes true. They are reverse of each other in logical expression. Choosing the correct loop between a while loop and until loop allows your program to be more readable and understandable by others or yourself when you come back to the code sometime later.
Some typical examples or reasons to use a until loop could be, loop until the user enters ‘exit’; loop until the data generated is greater than the requested data volume, or until a number of files that match your search are found.
The basic syntax of UNTIL loop looks like this:
LINES OF CODE
MORE LINES OF CODE
done
Now lets take some examples. The first example will multiple factor of two until reaching a size threshold of 1000:
NUM=1
until [ "$NUM" -gt 1000 ]; do
echo $NUM
let NUM=NUM*2
done
The second example will continue to ping a URL until the response time is greater than 100 milliseconds:
MILLISECONDS=0
# we will ping until it becomes slower than 1000 milliseconds
until [ $MILLISECONDS -gt 1000 ]
do
# run the ping and extract the line that has the ping time, which ends in time=XXXX ms
OUTPUT=`ping -c 1 google.com | grep time | awk -F= '{ print $NF }'`
echo "Ping time: $OUTPUT"
# extract number of milliseocnds from string as integer
MILLISECONDS=`echo $OUTPUT | awk '{ print $1 }' | awk -F. '{ print $1 }' `
echo "Number of ms = $MILLISECONDS"
sleep 1
done
echo "ping time exceeded 1000 milliseconds"
The third example will take a file and will combine the file with itself until it reaches 1 kilobyte in size:
FILENAME=`basename "$0"`
echo $FILENAME
TMP_FILE="./tmp1"
TARGET_FILE="./target"
cat $FILENAME > $TARGET_FILE
FILESIZE=0
# increase file size until 1KB
until [ $FILESIZE -gt 1024 ]
do
# add this file to target file content
cp $TARGET_FILE $TMP_FILE
cat $TMP_FILE >> $TARGET_FILE
FILESIZE=`du $TARGET_FILE | awk '{ print $1 }'`
echo "Filesize: $FILESIZE"
sleep 1
done
echo "new filesize reached target of 1KB"
The fourth example will ask the user for input of their name until they type exit to quit the program:
RESPONSE="FOO"
# increase file size until 1KB
until [ "$RESPONSE" = "exit" ]
do
echo -n "Enter your name or 'exit' to quit this program: "
read RESPONSE
if [ "$RESPONSE" != "exit" ]; then
echo "Hello $RESPONSE"
fi
done
echo "Thank you for playing this game"
CONCLUSION
The key point is to use UNTIL loop to make your code more clear when the condition is expected to be always false and then you want to stop your looping action when the condition becomes true. In other words, continue looping UNTIL some point in time. With this perspective I hope your bash scripts can be more clear and you have learned something with this article. Thank you.