Tcsh Aliases (2 of 3): Using tcsh history substitutions within aliases

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
$ popd

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 /tmp, while !: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 !:1 and !: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
first 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
second two
first one

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