Sometimes you want a script that will step through the command-line arguments one by one. (The 
"$@"
 parameter (
44.15
)
  gives you all of them at once.) The Bourne shell 
for
 loop can do this. The 
for
 loop looks like this:
for arg inlistdo ... handle $arg ... done
If you omit the 
in
 list
, the loop steps through the command-line arguments. It puts the first command-line argument in 
arg
 (or whatever else you choose to call the  
shell variable (
6.8
)
), then executes the commands from 
do
 to 
done
. Then it puts the next command-line argument in 
arg
, does the loop... and so on... ending the loop after handling all the arguments.
For an example of a for loop, let's hack on the zpg ( 44.12 ) script.
| case | #!/bin/sh # zpg - UNCOMPRESS FILE(S), DISPLAY WITH pg # Usage: zpg [pg options] file [...files] stat=1 # DEFAULT EXIT STATUS; RESET TO 0 BEFORE NORMAL EXIT temp=/tmp/zpg$$ trap 'rm -f $temp; exit $stat' 0 trap 'echo "`basename $0`: Ouch! Quitting early..." 1>&2' 1 2 15 files= switches= for arg do case "$arg" in -*) switches="$switches $arg" ;; *) files="$files $arg" ;; esac done case "$files" in "") echo "Usage: `basename $0` [pg options] file [files]" 1>&2 ;; *) for file in $files do gzcat "$file" | pg $switches done stat=0 ;; esac | 
|---|
We added a for loop to get and check each command-line argument. For example, let's say that a user typed:
%zpg -n afile ../bfile
The first pass through the 
for
 loop, 
$arg
 is 
-n
. Because the argument starts with a minus sign (
-
), the 
case
 treats it as an option. Now the 
switches
 variable is replaced by its previous contents (an empty string), a space, and 
-n
. Control goes to the 
esac
 and the loop repeats with the next argument.
The next argument, 
afile
, doesn't look like an option. So now the 
files
 variable will contain a space and 
afile
.
The loop starts over once more, with 
../bfile
 in 
$arg
. Again, this looks like a file, so now 
$files
 has 
 afile ../bfile
. Because 
../bfile
 was the last argument, the loop ends; 
$switches
 has the options and 
$files
 has all the other arguments.
Next, we added another 
for
 loop. This one has the word 
in
 followed by 
$files
, so the loop steps through the contents of 
$files
. The loop runs 
gzcat
 on each file, piping it to 
pg
 with any switches you gave.
Note that 
$switches
 isn't 
quoted (
8.14
)
. This way, if 
$switches
 is empty, the shell won't pass an empty argument to 
pg
. Also, if 
$switches
 has more than one switch, the shell will break the switches into separate arguments at the spaces and pass them individually to 
pg
.
You can use a for loop with any space-separated (actually, IFS ( 35.21 ) -separated) list of words - not just filenames. You don't have to use a shell variable as the list; you can use command substitution ( 9.16 ) (backquotes), shell wildcards ( 15.2 ) , or just "hardcode" the list of words:
| - lpr | for person in Joe Leslie Edie Allan do echo "Dear $person," | cat - form_letter | lpr done | 
|---|
The getopt and getopts ( 44.18 ) commands handle command-line arguments in a more standard way than for loops.
-
|   |   |   | 
| 44.15 Handling Command-Line Arguments in Shell Scripts |   | 44.17 Handling Arguments with while and shift | 
