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 inlist
do ...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.
-