It's convenient for your aliases to use command-line arguments. For example, let's think about an alias named phone:
alias phone 'cat ~/phonelist | grep -i'
After you define that alias, you could type phone
smith
. The shell would find the phone alias and execute it with the
argument (smith) at the end (Section 29.2) this way:
cat ~/phonelist | grep -i smith
Using cat and a pipe that way is inefficient (Section 43.2). It might be more sensible to have an alias that worked like this:
grep -i name
~/phonelist
How do
we do this? The C shell's history (Section 30.8) facility lets us use the
notation !$
to refer to the last word in the
previous command; the notation !*
refers to
all the arguments of the previous command. Assuming that we only want to look up
aliases one at a time, we can use !$
and
write our alias like this:
alias phone grep -i \!$ ~/phonelist
When we use the phone command, its final
argument will be substituted into the alias. That is, when we type phone bill
, the shell executes the command
grep -i bill ~/phonelist
.
In
this example, we needed another kind of
quoting. We had to put a backslash before the exclamation point to prevent the
shell from replacing !$
with the previous
command's last argument. That is, we don't want the shell to expand !$
when we define the alias — that's nonsense. We
want the shell to insert the previous argument when we use the alias (in which
case, the previous argument is just the argument for the alias itself —
clear?).
But why couldn't we just use single quotes or double quotes (Section 27.12)? This isn't the right place for a full explanation, but neither single quotes nor double quotes protect the exclamation point. The backslash does (Section 27.13). If you want to be convinced, experiment with some commands like:
%echo '!!'
Print your last command %echo '\!!'
Print !!
The first echo command shows that the shell performs history substitution
(i.e., replaces !!
with your previous
command) in spite of the single quotes. The second example shows that the
backslash can prevent the shell from interpreting !
as a special character.
Let's look at another alias. We want to pipe the output of ls -l into more. In this case, we would want all the arguments from the command line instead of merely the last argument (or the only argument). Here's the alias:
alias lm 'ls -l \!* | more'
This time, we needed both kinds of
quoting: a backslash prevents the shell from interpreting the exclamation point
immediately. Single quotes protect the pipe symbol and the asterisk (*
). If you don't protect them both, and protect
only the pipe (with a backslash), look what happens:
% alias lm ls -l \!* | more
alias: No match.
Because the backslash temporarily stops the special meaning of the !
, the shell next tries to find filenames that
match the wildcard (Section 1.13) pattern !*
. That fails (except in the unusual case when
you have a file in the current directory whose name starts with a !
).
Here's a good general rule for quoting aliases. Unless you're trying to do
something special with an alias and you understand quoting well, put single
quotes ('
) around the whole definition
and put a backslash before every exclamation point (\!
).
If you want to pick one argument from the command line, use \!
:n
, where
n
is the number of the argument. Here's a sample
alias. It uses cat (Section 12.2) to add a header file to
the file named in the first argument, then writes them both into the file named
in the second argument:
alias addhead 'cat ~/txt/header \!:1 > \!:2'
This alias has two arguments: the file to which you want to add a header and the output file. When you type:
% addhead foo bar
the C shell substitutes the filename foo
for \!:1
, and the filename bar
for \!:2
,
executing the command:
cat ~/txt/header foo > bar
Finally, if you need to append fixed text strings to these arguments, you need
to separate the argument text from the fixed text. For instance, here's an alias
that tells the Netscape browser to go to a URL
http://info/proj23/
xxx1.html
, where xxx
is a
word like report, summary, etc., that
you're typing on the command line (as an argument to the alias). For instance,
to go to the page http://info/proj23/report1.html, you'd
type:
% proj report
The first alias below shows the wrong way to do this. The second one shows how
to quote the argument in curly braces ({}
) so the shell doesn't think the 1
after the argument is part of the number (giving
you argument 11 instead of what you want: argument 1 with the digit
1 after it):
alias proj 'netscape -remote "openURL(http://info/proj23/\!:11.html)"' ...wrong alias proj 'netscape -remote "openURL(http://info/proj23/\!{:1}1.html)"' ...right
If you haven't seen this netscape
-remote
technique, by
the way, it's very handy. It sends a message to an already-open Netscape
browser. You can use it from a command line (shell prompt) or by defining a
button or menu item on your window system desktop. Recent Unix versions of
Mozilla have also begun to support this API, as well. On the Macintosh, remote
control is supported via Apple Events, but not from the command line as of this
writing.