home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam

 Chapter 8How the Shell Interprets What You Type

## 8.12 Which One Will the C Shell Use?

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

1. strips the 8th bit of each byte of each word

2. 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.)

- CT on Usenet, 14 November 1990

 8.11 Which One Will bash Use? 8.13 Is It "2>&1 file" or "> file 2>&1"? Why?