Rc — The Plan 9 Shell

Tom Duff



Rc is a command interpreter for Plan 9 that provides similar facilities to UNIX’s Bourne shell, with some small additions and less idiosyncratic syntax. This paper uses numerous examples to describe rc’s features, and contrasts rc with the Bourne shell, a model that many readers will be familiar with.

1. Introduction

Rc is similar in spirit but different in detail from UNIX’s Bourne shell. This paper describes rc’s principal features with many small examples and a few larger ones. It assumes familiarity with the Bourne shell.

2. Simple commands

For the simplest uses rc has syntax familiar to Bourne-shell users. All of the following behave as expected:


cat /lib/news/build

who >user.names

who >>user.names

wc <file

echo [a-f]*.c

who | wc

who; date

vc *.c &

mk && v.out /*/bin/fb/*

rm -r junk || echo rm failed!

3. Quotation

An argument that contains a space or one of rc’s other syntax characters must be enclosed in apostrophes ():

rm ’odd file name’

An apostrophe in a quoted argument must be doubled:

echo ’How’’s your father?’

4. Patterns

An unquoted argument that contains any of the characters * ? [ is a pattern to be matched against file names. A * character matches any sequence of characters, ? matches any single character, and [class] matches any character in the class, unless the first character of class is ~, in which case the class is complemented. The class may also contain pairs of characters separated by -, standing for all characters lexically between the two. The character / must appear explicitly in a pattern, as must the path name components . and ... A pattern is replaced by a list of arguments, one for each path name matched, except that a pattern matching no names is not replaced by the empty list; rather it stands for itself.

5. Variables

UNIX’s Bourne shell offers string-valued variables. Rc provides variables whose values are lists of arguments — that is, arrays of strings. This is the principal difference between rc and traditional UNIX command interpreters. Variables may be given values by typing, for example:

path=(. /bin)



The parentheses indicate that the value assigned to path is a list of two strings. The variables user and font are assigned lists containing a single string.

The value of a variable can be substituted into a command by preceding its name with a $, like this:

echo $path

If path had been set as above, this would be equivalent to

echo . /bin

Variables may be subscripted by numbers or lists of numbers, like this:

echo $path(2)

echo $path(2 1 2)

These are equivalent to

echo /bin

echo /bin . /bin

There can be no space separating the variable’s name from the left parenthesis; otherwise, the subscript would be considered a separate parenthesized list.

The number of strings in a variable can be determined by the $# operator. For example,

echo $#path

would print 2 for this example.

The following two assignments are subtly different:



The first sets empty to a list containing no strings. The second sets null to a list containing a single string, but the string contains no characters.

Although these may seem like more or less the same thing (in Bourne’s shell, they are indistinguishable), they behave differently in almost all circumstances. Among other things

echo $#empty

prints 0, whereas

echo $#null

prints 1.

All variables that have never been set have the value ().

Occasionally, it is convenient to treat a variable’s value as a single string. The elements of a string are concatenated into a single string, with spaces between the elements, by the $" operator. Thus, if we set

list=(How now brown cow)


then both

echo $list


echo $string

cause the same output, viz:

How now brown cow


echo $#list $#string

will output

4 1

because $list has four members, but $string has a single member, with three spaces separating its words.

6. Arguments

When rc is reading its input from a file, the file has access to the arguments supplied on rc’s command line. The variable $* initially has the list of arguments assigned to it. The names $1, $2, etc. are synonyms for $*(1), $*(2), etc. In addition, $0 is the name of the file from which rc’s input is being read.

7. Concatenation

Rc has a string concatenation operator, the caret ^, to build arguments out of pieces.

echo hully^gully

is exactly equivalent to

echo hullygully

Suppose variable i contains the name of a command. Then

vc $i^.c

vl -o $1 $i^.v

might compile the command’s source code, leaving the result in the appropriate file.

Concatenation distributes over lists. The fo