sections in this module City College of San Francisco - CS160B
Unix/Linux Shell Scripting
Module: Loops2
module list

Which Loop?

As discussed previously, the while loop is more general than the for loop. However, since the while loop relies on another command to exit the loop, it can easily become infinite. The for loop, on the other hand, always stops when the list is exhausted. This makes the for loop the loop of choice if you have a choice. The question about which loop, then, boils down to this: Can I use a for loop?

Can I use a for loop

The great majority of loops in existing shell code are for loops. However, in order to use a for loop, you must be able to create a list that will be processed correctly. The following must be true

This sounds complicated. But there are two common situations where they are true

  1. you want to run a loop on the words produced by the output of a Unix command. Here, a word is a sequence of non-whitespace characters.
  2. you want to run a loop on a set of filenames that match a pattern. So long as you generate the list with a wildcard, this is fine.
Here are a couple of cases where for loops work well:

Example

the groups command outputs the groups you are member of:

$ groups
cisdept labstaff c36471 c36505 c36536 c36538 c38703 c39302 c39303 c76115 c76120 c76131 c77036 c78728

If you wanted to execute some commands on each group you are member of, you could begin the loop like this:

for group in $(groups); do

Example

Here are a few for statements extracted from standard system administration shell scripts on linux:

This example simply lists static directory paths to process.Here a wildcard (or set of wildcards) is used to generate the list, so the filenames generated may contain whitespace ($IFS characters). The variables ($i and $afile) must be enclosed in double-quotes in the loop.These examples use a substitution to generate the list. In these cases, the list elements may not contain $IFS delimiters.

Each of these lists must be "not too big". Using a wildcard to list a directory or set of directories is usually safe. The following loop, however, is suspect:

for path in $(find . -type f); do

Since find is recursive, it can generate a lot of output. Further, since paths are being generated and the result is substituted on the command-line using a $ substitution, the text is broken up using whitespace (actually $IFS). Thus, filenames that include spaces will cause problems.

When to use while

If you can use a for loop easily, use it. If you can't list the things processed, or the list is unbounded, a while loop is the loop of choice. To see how while loops are used, let's look at some examples found on our linux systems:

These while loops use a flag variable to control when the loop exits. The flag variable is altered in the loop. Here the counter is either boolean (in the case of $checking) or an integer counter (in the case of $STARTTIMEOUT)

This loop is infinite. The : is a null command. It has the same effect as the true command. This loop must be exited either by an exit or break command in the loop body.

This loop uses a combination of a command (check_devide_down) and a counter variable ($waited). The loop stops when the device status changes (check_device_down succeeds) or when the counter variable passes 50. The counter is incremented in the loop body.

This more advanced example runs a command that finds the process id of a program identified by its program's name ($prog). As long as a program by that name is running, pidof succeeds. The loop thus continues until all instances of the program are killed. (yes, this is advanced)

This familiar example is used to process command-line arguments. The loop continues while there are arguments. The arguments in a loop like this are typically processed one per iteration, using $1 as the current argument. At the end of each iteration, a shift command is used to delete the argument that was just processed, and decrement $#.

This last example is the subject of our next section, the while read loop. It is one of the most powerful loops there is: if you can create a list of items to process, one item per line, you can process the list using a while read loop. The list is line-oriented, so list items can contain whitespace. 

Preview question: In a previous question, we discussed how you can connect standard output to a shell script, a function, or even an if statement. What does the following loop do?
while read line; do
echo "$line"
done
Type this loop into the shell. Then start typing. What happens when you hit ENTER? What happens when you type a control-D? Can you explain this?

Prev This page was made entirely with free software on linux:  
Kompozer
and Openoffice.org    
Next

Copyright 2009 Greg Boyd - All Rights Reserved.

Document made with Kompozer