[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 ORed 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