To write flexible shell scripts, you usually want to give them command-line arguments. As you've seen in 
other articles (
44.11
, 
44.12
)
, 
$1
 holds the first command-line argument. The Bourne shell can give you arguments through the ninth, 
$9
. The Korn Shell and some other newer Bourne-type shells understand 
${10}
 for the tenth argument, and so on. (Article 
8.5
 has an overview of the shell's command-line handling.)
If you've been reading this 
series (
44.1
)
 of articles in order, you saw the 
zpg
 (
44.12
)
 script that accepted just one command-line argument.
 If you put 
"$@"
 in a script, the shell will replace that string with a 
quoted (
8.14
)
 set of the script's command-line arguments. Then you can pass as many arguments as you want, including pathnames with 
unusual characters (
23.11
)
:
%zpg report memo "savearts/What's next?"
The third argument has a perfectly legal filename; we see more and more of them on our system - especially filesystems that are networked to computers like the Macintosh, where spaces and other "special" characters in filenames are common. Double-quoting all arguments through the script helps to be sure that the script can handle these unusual (but legal!) pathnames.
In this case, we want the arguments to be passed to the gzcat command. Let's change the zpg script to read:
gzcat "$@" >$temp
When the shell runs the script with the arguments shown above, the command line will become:
gzcat "report" "memo" "savearts/What's next?" >/tmp/zpg12345
NOTE: On some Bourne shells, if there are no command-line arguments, the
"$@"becomes a single empty argument ( 46.7 ) , as if you'd typed this:
gzcat "" >/tmp/zpg12345In this case, the gzcat command would complain that it can't find a file. (Of course, in this script, the case would prevent this problem. But not all scripts test the number of arguments.)
On those shells, you can replace
"$@"with${1+"$@"}( 45.12 ) . That means that if$1is defined,"$@"should be used. A less-good fix is to replace"$@"with$*. It gives you an unquoted list of command-line arguments; that's usually fine but can cause trouble on pathnames with special characters in them.
A 
for
 loop (
44.16
)
 can step through all command-line arguments, one by one. You can also use a 
while
 loop (
44.10
)
 that tests 
$#
 (see later in this chapter) and removes the arguments one by one with the 
shift
 command (
44.17
)
. The 
getopt
 and 
getopts
 (
44.18
)
 commands handle arguments in a more standard way.
The 
$#
 parameter counts the number of command-line arguments. For instance, if there are three arguments, 
$#
 will contain 
3
. This is usually used for error-checking (as in the 
zpg
 script in article 
44.12
) with 
case
 (
44.5
)
 or 
test
 (
44.20
)
.
-
|   |   |   | 
| 44.14 Putting awk, sed, etc., Inside Shell Scripts |   | 44.16 Handling Command-Line Arguments with a for Loop | 
