[Most of this article, except IFS and
--
, also applies to the C shell. —
JP]
You can pass options and arguments to a shell as you start it, as in:
sh -v file1 file2
and also when a script is invoked with #!
.
The set command lets you set command-line
parameters, including most[9] shell options, after you've started the shell. This simple idea has
more uses than you might realize.
The Bourne shell command line can have
options like -e
(exit if any command returns nonzero
status). It can also have other arguments; these are passed to shell
scripts. You can set new command-line parameters while you're typing
interactive commands (at a shell prompt) or in a shell script.
To reset the command-line parameters, just type set followed by the new parameters. For example, to ask the shell to show expanded versions of command lines after you type them, set the -v (verbose) option (Section 27.15):
$set -v
$mail $group1 < message
mail andy ellen heather steve wilma < message $mail $group2 < message
mail jpeek@jpeek.com randy@xyz.edu yori@mongo.medfly.com < message $set +v
On many Bourne shells, typing set +v
cancels the v
option. On other (mostly early) shells,
there's no +
feature. To work around that
problem, you could start a subshell (Section 24.4) with sh -v
, run the commands there, then exit the
subshell to cancel the verbose option.
Go to http://examples.oreilly.com/upt3 for more information on: users
You
can put filenames or any other strings in the
command-line parameters interactively or from a shell script. That's handy
for storing and parsing the output of a Unix command with backquotes (Section 28.14). For example, you can get a list of all logged-in
users from the parameters $1
, $2
, and so on. Use users
(or rusers to find all the logged in users on the local network)
if your system has it. Otherwise, use who
(
Section 2.8) and cut (Section
21.14) to strip off everything but the usernames:
for
Section 35.21
$set `users`
$set `who | cut -c1-8`
$for u
>do
> ...do something with each user ($u)... >done
You can save the original parameters in another variable and reset them later:
oldparms="$*"
set something new
...use new settings...
set $oldparms
Be sure to watch your quoting (as the next section explains).
If the first parameter you set starts with a dash, like -e
, the shell will treat it as its own option
instead of as a string to put into the command-line parameters. To avoid
this, use --
(two dashes) as the first
argument to set. In this example,
$1
gets -e
, and the
filenames expanded from the wildcard pattern go into $2
, $3
,
etc.:
set -- -e file*
If you type set by itself with no arguments, it will show a list of all currently set shell variables. In newer Bourne-type shells, it also shows shell functions (Section 29.11) and other shell settings.
This can cause you grief if you accidentally don't pass arguments to
set in the middle of a script, and
screenfuls of variables spew onto the user's screen. For example, your
script runs set 'users'
from a cron (Section
25.2) job, in the middle of the night when no one is logged on.
The users command returns an empty
string, so set gets no arguments, so it
outputs a long list of junk.
The standard workaround for this problem is to always use a dummy first
parameter — typically, a single x
— when
you're setting parameters. Then use shift
(Section 35.22) to shift away
the x
, leaving the other parameters
(possibly none). For example:
set x `users` shift
Because the shell parses and scans the new parameters before it stores them, wildcards (Section 33.2) and other special characters (Section 27.17) will be interpreted, so watch your quoting (Section 27.12). You can take advantage of this to parse lines of text into pieces that aren't separated with the usual spaces and TABs — for instance, a line from a database with colon-separated fields — by setting the IFS (Section 36.23) variable before the set command.
If you want to save any special
quoting on the original command line, be careful: the quoting will be lost
unless you're clever. For example, if $1
used to be John Smith, it will be split after it's
restored: $1
will have
John and $2
will
be Smith. A better solution might be to use a subshell (Section 43.7) for the part of the script where you need to reset
the command-line parameters:
# reset command-line parameters during subshell only:
(set some new parameters
...do something with new parameters...
)
# original parameters aren't affected from here on...
[9] Some options for some shells can be set only from the command line as the shell is invoked. Check the shell's manual page.