Looping Through a List of Arguments

[previous] [next] [table of contents] [index]

You can use the Bourne shell's for loop to step through a list of arguments one by one. The C shell has a foreach loop with a different syntax. These loops aren't useful just for programming; they're good any time you need to repeat an operation on several messages or several folders.

The Bourne shell for loop looks like this:

for arg in list
do
    ...Handle $arg...
done
If you omit the in list, the loop steps through the command-line arguments.

The loop puts its first argument in the arg shell variable, then executes the commands from do to done. Then it puts the next argument in arg, does the loop... and so on... ending the loop after handling all the arguments. For example, to search five folders for a message (and store a list of matches in the folder's picked sequence):

for folder in inbox outbox top/sub1 top/sub2 project
do
    echo Checking +$folder
    pick -subject "Something" -sequence picked +$folder
done
That loop would print something like:
Checking +inbox
pick: No messages meet specification
Checking +outbox
2 hits
Checking +top/sub1
    ...
Let's use an interactive example for the C shell. When you use a loop interactively, the shells print prompts:
% foreach folder (inbox outbox top/sub1 top/sub2 project)
? echo Checking +$folder
? pick -subject "Something" -sequence picked +$folder
? end
Checking +inbox
pick: No messages meet specification
Checking +outbox
2 hits
Checking +top/sub1
    ...
If you have a shell variable with one or more words in it, you can use that as the list for the loop. The list will be split at the spaces. For example, in the Bourne shell:
msgs="first cur last"
    ...
for msg in $msgs
do
    ...Process $msg...
done
The next Example shows how a Bourne shell script can find the options and arguments from a command line.

Example: for loop parsing a command line

folder= switches=
for arg
do
   case "$arg" in
   [+@]*) # IT'S A FOLDER
      case "$folder" in
      "") folder="$arg" ;;
      *) echo "`basename $0`: '$arg'?  Only one folder at a time." 1>&2
         exit 1
         ;;
      esac
      ;;
   *) switches="$switches $arg" ;;
   esac
done
Because the for arg line doesn't have a list of arguments, the loop gets and checks each argument from the command line. For an example, let's say that a user typed:
% progname +project -nocc to
The first pass through the for loop, $arg is +project. Because the argument starts with a plus sign (+) or an at sign (@), the case treats it as a folder name. If there was a folder name in some earlier argument, an error is printed and the script exits (with a nonzero status, to signal an error). In this example, though, this is the first folder name, so +project is stored in in the folder shell variable. Then the loop repeats with the next argument.

The next argument, -nocc, doesn't look like a folder name. So the switches variable is replaced by its previous contents (an empty string), a space, and -nocc. The loop starts over once more, with to in $arg; this also doesn't look like a folder name, so now switches has its previous contents followed by a space and the new $arg. Now $switches is -nocc to. Because to was the last argument, the loop ends; $folder has the folder name and $switches has all the other arguments.

[Table of Contents] [Index] [Previous: Using Exit Status] [Next: Finding Program Name; Multiple Program Names]


Last change $Date: 1996/06/06 15:10:41 $

This file is from the third edition of the book MH & xmh: Email for Users & Programmers, ISBN 1-56592-093-7, by Jerry Peek. Copyright © 1991, 1992, 1995 by O'Reilly & Associates, Inc. This file is freely-available; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. For more information, see the file copying.htm.

Suggestions are welcome: Jerry Peek <jpeek@jpeek.com>