9.5. Break and continue
9.5.1. The break built-in
The break statement is used to exit the current loop before its normal ending. This is done when you don't know in advance how many times the loop will have to execute, for instance because it is dependent on user input.
The example below demonstrates a while loop that can be interrupted. This is a slightly improved version of the wisdom.sh script from Section 18.104.22.168.
# This script provides wisdom
# You can now exit in a decent way.
while true; do
echo "On which topic do you want advice?"
echo "1. politics"
echo "2. startrek"
echo "3. kernelnewbies"
echo "4. sports"
echo "5. bofh-excuses"
echo "6. magic"
echo "7. love"
echo "8. literature"
echo "9. drugs"
echo "10. education"
echo -n "Enter your choice, or 0 for exit: "
case $choice in
echo "Sports are a waste of time, energy and money."
echo "Go back to your keyboard."
echo -e "\t\t\t\t -- \"Unhealthy is my middle name\" Soggie."
echo "OK, see you!"
echo "That is not a valid choice, try a number from 0 to 10."
Mind that break exits the loop, not the script. This can be demonstrated by adding an echo command at the end of the script. This echo will also be executed upon input that causes break to be executed (when the user types "0").
In nested loops, break allows for specification of which loop to exit. See the Bash info pages for more.
9.5.2. The continue built-in
The continue statement resumes iteration of an enclosing for, while, until or select loop.
When used in a for loop, the controlling variable takes on the value of the next element in the list. When used in a while or until construct, on the other hand, execution resumes with TEST-COMMAND at the top of the loop.
In the following example, file names are converted to lower case. If no conversion needs to be done, a continue statement restarts execution of the loop. These commands don't eat much system resources, and most likely, similar problems can be solved using sed and awk. However, it is useful to know about this kind of construction when executing heavy jobs, that might not even be necessary when tests are inserted at the correct locations in a script, sparing system resources.
[[email protected] ~/test] cat tolower.sh
# This script converts all file names containing upper case characters into file# names containing only lower cases.
for name in "$LIST"; do
if [[ "$name" != *[[:upper:]]* ]]; then
NEW=`echo $name | tr 'A-Z' 'a-z'`
mv "$ORIG" "$NEW"
echo "new name for $ORIG is $NEW"
This script has at least one disadvantage: it overwrites existing files. The noclobber option to Bash is only useful when redirection occurs. The -b option to the mv command provides more security, but is only safe in case of one accidental overwrite, as is demonstrated in this test:
[[email protected] ~/test] rm *
[[email protected] ~/test] touch test Test TEST
[[email protected] ~/test] bash -x tolower.sh
+ [[ test != *[[:upper:]]* ]]
+ [[ Test != *[[:upper:]]* ]]
++ echo Test
++ tr A-Z a-z
+ mv -b Test test
+ echo 'new name for Test is test'
new name for Test is test
+ [[ TEST != *[[:upper:]]* ]]
++ echo TEST
++ tr A-Z a-z
+ mv -b TEST test
+ echo 'new name for TEST is test'
new name for TEST is test
[[email protected] ~/test] ls -a
./ ../ test test~
The tr is part of the textutils package; it can perform all kinds of character transformations.