Csh, alias substitution, & backslash
Chris Torek
chris at mimsy.umd.edu
Wed Nov 14 19:58:30 AEST 1990
(this almost certainly belongs in comp.unix.shell, so I have redirected
followups there, not that I actually expect any)
In article <6663 at ge-dab.ge.com> brooks at ge-dab.ge.com (Stephen Brooks) writes:
> In the C-shell, you can prevent alias substitution by preceding the
>aliased command with a backslash. ... why does "\rm" work, but "\cd"
>does not? Yes, I realize that "cd" is a C-shell builtin command, but
>I haven't been able to find any discussion on how the \ prevents alias
>substitution.
It is a side effect.
The C shell first breaks each input line into a `word vector'. It
then matches against aliases. Since `\rm' does not match `rm', any
alias is ignored. Eventually the C shell fully applies any quoting
(since an alias can include quotes, some of this work must be deferred;
since an alias can include multiple words, more word vector work must
be done as well; it all gets rather hairy).
The C shell implements quoting by setting the 8th bit (bit 7) of each
byte of a quoted character. Since '*'|0x80 is not the same character
as '*', this prevents file name expansion, further word breaking, and
so on.
Eventually, the shell has a fully `parsed' line. It then compares
word[0] against all the built-ins. If there is a match, it runs the
corresponding built-in command (and it is up to that command to expand
any remaining words; for instance, `ls *' in a directory containing
only the file `-l' produces a long listing, but `jobs *' produces
a usage message). If not, the shell performs globbing on the current
word list, producing a new word list, and then:
a) strips the 8th bit of each byte of each word
b) exec()s the resulting command.
This means that
\cd
not only bypasses any alias, but also reaches the built-in scanner as
'c'|0x80, 'd', '\0'
which does not match the built-in command
'c', 'd', '\0'
and so does not run the `cd' builtin. It is later stripped and the shell
looks for an external program called `cd'.
If you want to avoid alias substitution, but not built-in matching,
you can replace
\cd foo
or
\rm foo
with
''cd foo
or
""rm foo
These do not match the aliases---during alias scanning they
have quote pairs in front of them---but do match any builtin
since the quotes have by then been stripped (setting bit 7 of
all the characters contained between the two quotes, here none).
Incidentally, since alias expansion occurs early, you can do
some peculiar things with it:
% [
Missing ].
% alias [ echo foo
% [
foo
(alias expansion occurs before globbing)
% unalias [
unalias: Missing ].
(unalias globs its arguments!)
% unalias \[
% alias unalias echo foo
unalias: Too dangerous to alias that.
(the C shell attempts caution...)
% alias \unalias echo foo
% alias
unalias (echo foo)
% unalias unalias
foo unalias
(but fails!)
% ''unalias unalias
% alias
%
(Fortunately, there is an exit.)
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750)
Domain: chris at cs.umd.edu Path: uunet!mimsy!chris
More information about the Comp.unix.questions
mailing list