[Article
8.11
shows how to control whether
bash
uses a built-in command, a shell function, or an external command. The way you do that in the C shell is a little, errr, different.
Chris Torek explains why, for example,
\rm
disables an alias for
rm
and
\cd
disables the built-in
cd
command. He starts with a fairly complex explanation, then gives some practical guidelines. At the end is a "review" that's easy to follow and fun too. -JP]
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
[a character
OR
ed with 80 hex a.k.a. 10000000 binary-
JP
] 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]
[the first word on the command line-
JP
] 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 [filename wildcard expansion-
JP
] on the current word list, producing a new word list, and then:
strips the 8th bit of each byte of each word
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.)
- on Usenet, 14 November 1990