Continuing our tutorial on tcsh aliases we look at combining aliases with history substitutions. Both aliases and history substitutions are useful tools, but it may not be obvious that they work well together. The tcsh man page says:
After a command line is parsed into simple commands the first word of each command, left-to-right, is checked to see if it has an alias. If so, the first word is replaced by the alias. If the alias contains a history reference it undergoes history substitution as though the original command were the previous input line. If the alias does not contain a history reference, the argument list is left untouched.
The crucial point here is that history substitutions can be used within an alias to refer to the original command typed by the user. Suppose we often type
pushd to change to another directory then run some command and finally type
popd to return to the original directory. Perhaps we might like to replace a sequence of commands such as
$ pushd /tmp
$ ls -l
with the shorter command:
$ in /tmp ls -l
We can achieve this by defining an alias such as:
$ alias in 'pushd \!:1 ; \!:2* ; popd'
The !:1 in this alias refers to the first word following
in, in this case
!:2* means all the remaining words on the command line, in this case
ls -l. So when we type
$ in /tmp ls -l
it has the same effect as typing
$ pushd /tmp ; ls -l ; popd
Quoting and Aliases
When defining this alias we have to escape
!:2 with a backslash (“\”), so that they become a part of the alias itself, rather than themselves being replaced by the first and subsequent words of what we are typing. Quoting issues such as this are probably one of the most confusing aspects of defining an alias. Stephen Bloch’s notes on the subject are very helpful.
Extracting a List of Aliases
You can check what aliases are defined by typing the word
alias by itself. Along with any other aliases that you have defined, it will report:
ll ls -l
ls ls --color=tty
in pushd !:1 ; !:2* ; popd
Limitations when using Aliases
The alias mechanism, although quite powerful, does have its limitations. For example if you define a “printfirst” alias which echoes its first argument, it works as expected.
$ alias printfirst 'echo first \!:1'
$ printfirst one
Similarly, a more complicated alias to echo the second argument and then echo the first argument also works just as you would hope.
$ alias works 'echo second \!:2 ; echo first \!:1'
$ works one two
But if you try to use printfirst alias within another alias, you’ll probably get an error.
$ alias fails 'echo second \!:2 ; printfirst'
$ fails one two
Bad ! arg selector
Obviously you can work around such problems, but if you find yourself dealing with this sort of complexity then it’s probably worth spending a few more minutes to write a shell script instead of an alias.
Next time we’ll look at the issues that arise when an alias is used as an input to another program.
Author: Richard Jordan is a developer at Ellexus