[Update] the C Shell | csh – POLLICELEE

csh: นี่คือโพสต์ที่เกี่ยวข้องกับหัวข้อนี้

Last modified: Fri Nov 27 09:44:52 2020

Check out my other tutorials on the Unix Page, and my

Check my blog

Copyright 1994, 1995 Bruce Barnett and General Electric Company

Copyright 2001, 2013 Bruce Barnett

All rights reserved

You are allowed to print copies of this tutorial for your personal
use, and link to this page, but you are not allowed to make electronic
copies, or redistribute this tutorial in any form without permission.

Original version written in 1994 and published in the Sun Observer

This section describes C Shell (CSH/TCSH) programming.
It covers conditional testing, control loops, and other advanced techniques.

This month begins a tutorial on the bad-boy of UNIX, lowest of the low,
the shell of last resort. Yes, I am talking
about the C shell.
FAQ’s flame it. Experts have criticized it.
Unfortunately, this puts UNIX novices in an awkward
situation.
Many people are given the C shell as their default shell.
They aren’t familiar with it, but they have to learn
enough to customize their environment.
They need help, but get criticized every time they ask a question.
Imagine the following conversation, initiated by a posting on USENET:

Novice: How do I do XYZ using the C shell?

Expert: You shouldn’t use the C shell. Use the Bourne shell.

Novice: I try to, but I get syntax errors.

Expert: That’s because you are using the C shell. Use the Bourne shell.

Novice: I’ve now using the Bourne shell. How to I create aliases
and do command-line editing in the Bourne shell?

Expert: You can’t. use bash, ksh or tcsh.

Novice: I don’t have these shells on all of the systems I use.
What can I use?

Expert: In that case, use the C shell.

Novice: But you told me I shouldn’t use the C shell!?!

Expert: Well, if you have to, you can use the C shell.
It’s fine for interactive sessions.
But you shouldn’t use it for scripts.

Novice: It’s really confusing trying to learn two shells
at once. I don’t know either shell very well, and
I’m trying to learn
JUST enough to customize my environment.
I’d rather just learn one shell at a time.

Expert: Well, it’s your funeral.

Novice: How do I do XYZ using the C shell?

Another Expert: You shouldn’t be using the C shell. Use the Bourne shell.

Novice: @#%&!

The C shell does have problems.
(See My top 10 reasons not to use the C shell.)

Some can be fixed.
Others cannot.
Some are unimportant now, but later on might cause grief.
I’ll mention these problems. But I’ll let you decide
if you want to continue to use the C shell, or start using the Bourne shell.
Switching shells is difficult,
and some may wish to do so gradually.
If you want to use the C shell, that’s fine.
I’ll show you the pitfalls, so you can intelligently decide.
No pressure. You can switch at any time.
But be aware that the C shell is seductive.
It does have some advantages over the Bourne shell.
But sometimes what seems like an advantage turns into a disadvantage later.
Let me discuss them in detail.

The first problem I faced with the C shell involved another language.
I had a problem that required a
or
script.
The C shell has a
“feature” that warns programmers if they forgot to
terminate a quoted string. The following command
will generate a warning in the C shell:

echo “This quote doesn’t end

The Bourne shell would continue till the end of the script.
This is a good feature for an interactive shell,
as it warns you if you forgot to close a quote. But if you want to include a multi-line string, such as an
script inside a C shell script, you will have problems.
You can place a backslash at the end of each line,
but this is error prone, and also hard to read.
Some
constructs require a backslash at the end.
Using them inside a C shell script would require two backslashes in a row.

There are some other strange quoting problems.
Like the Bourne shell, the C shell has three ways to quote
characters. You can use the single quote, double quote and backslash.
But combine them, and find some strange combinations.
You can put anything inside single quotes in a Bourne shell script,
except single quotes.
The C shell won’t let you do that.
You can type

echo hi!

but the following generates an error:

echo ‘hi!’

You have to use a backslash if you want to do this:

echo ‘hi\!’

Also, the following
works:

echo money$

but this generates an error:

echo “money$”

But in this case you cannot even use a backslash.
The followings an error in the C shell:

echo “money\$”

Unix shells have many special characters, and quoting them marks them as normal ASCII – telling the shell not to interpret them. And this is true with every Unix shell there is, except the C shell. In the above cases, putting quotes around some characters
them special in the C shell, instead of
preventing the special interpretation.
Strange, huh?

The second problem is subtle, but may be the next problem you
discover. The Bourne shell has a true syntax parser: the
lines are scanned, and broken up into pieces. Some pieces are commands.
Other pieces are quoted strings. File redirection is handled the same way.
Commands can be combined on one line, or span several lines.
It doesn’t matter.
As an example, you can use

if true; then echo yes; fi

or

if true
then
echo yes
fi

The parsing of file redirection is independent of the particular command.
and
commands can get file redirection anywhere. The following
is valid in the Bourne shell:

echo abc | while read a
do
echo a is $a
done >/tmp/f1

The same holds true for other Bourne shell commands.
Once you learn the principles, the behavior is predictable.

The C shell does not have a true parser.
Instead, the code executes one section for the
command, and another for the
command.
What works for one command may not work for another.
The
command above cannot be done in the C shell.
There are two file redirections, and the C shell can’t do either.
Also, in the C shell, certain words
must be the first word on the line.
Therefore you might try something that works with one command,
only to discover that it doesn’t work on other commands.
I’ve reported a lot of bugs to Sun, and to their credit, many have been fixed.
Try the same code on other systems, however, and you might get syntax errors.

The parsing problem is also true with shell built-in commands. Combine them, and
discover strange messages. Try the following C shell sequence:

time | echo

versus

time | /bin/echo

and notice the strange error message.
There are other examples of this.
These are the types of problems that sneak up on you when you
don’t expect them.
The Bourne shell has the
flag, which lets you check the script for syntax errors,
including branches you didn’t take.
You can’t do this with the C shell.
The C shell seems to act on one line at a time and
some syntax errors may not be discovered unless they get executed.

Sometimes you have to ask a person for input in the middle of a script.
Sometimes you have to read some information from a file.
The Bourne shell allows you to specify the source of information
for each command.
Even though a script is connected to a pipe, you can ask the user for input.
The C shell does not have this flexibility.
It has a mechanism to get a line from standard input, but that is all it can do.
You cannot have a C shell script get input from both a file and the terminal.

With respect to file redirection, the Bourne shell
has no limitations, while the C shell is very limited.
With the Bourne shell, you can send standard error
to one place, and standard out to another file.
You can discard standard output, but keep the error.
You can close any file descriptor, save current ones, and restore them.
The C shell can’t do any of these steps.

If you want to make your script more robust, you must add
signal processing to it. That is, your script must terminate
gracefully when it is aborted. The C shell has limited abilities.
You can either do nothing, ignore all signals, or trap all signals.
It’s an all or nothing situation.
The Bourne shell can trap particular signals, and call a special routine
when the script exits normally.
You can retain the process ID of a background process.
This allows you to relay signals received to other processes under your control.
The C shell cannot do this.

You can use the C shell for simple scripts.
If you don’t add many new features, and only write scripts for yourself,
the C shell may be fine for you.
But it is a time bomb. There are many times
I wanted to add a new feature to a C shell script,
and couldn’t because it didn’t support the idea.
Or else I tried to port a C shell script to a different system
and found that it didn’t work the same way.
Yes, you can use the C shell.
Use it for as long as you want.
Your choice.

Tick…. Tick… Tick…

This is my second tutorial on the C shell. This month, I will discuss
quoting and meta-characters.

Like all shells, the C shell examines each line, and breaks it up into
words. The first word is a command, and additional words are
arguments for the command. The command

more *

uses a meta-character, the asterisk.
The shell sees the asterisk, examines the current directory, and transforms
the single character to all of the files in the current directory.
The
“more” program then displays all of the files.
There are many other meta-characters. Some are very subtle.
Consider this meta-character example:

more a b

The meta-character? It’s the space.
In this case, the space indicates the end of one filename
and the start of the next filename.
The space, tab, and new-line-character are used by the C shell to
indicate the end of one argument, and the beginning of the next.
(The Bourne shell allows more control, as any character can be
specified to have this function).

These meta-characters are an integral part of UNIX. Or rather, an integral part
of the shell.
A meta-character is simply a character with
a special meaning.
The file system doesn’t really care about meta-characters.
You can have a filename that contains a space, or an asterisk, or any other
character. Similarly, you can specify any meta-character as an argument
to any command. Understanding which characters are meta-characters, what they
do, and how to prevent them from being special characters is a skill that must
be learned. Most learn by trial and error. Trouble is, the C shell is trickier
than other shells.

One way to discover these characters is to use the
echo built-in command, and see which characters the C shell will echo, and which
ones are treated special.
Here is the list of meta-characters, and a quick description of the
special meaning.

+-----------------------------------------------------------------------+
|		    List of C Chell Meta-Characters			|
+-----------------------------------------------------------------------+
|Meta-character	  Meaning						|
+-----------------------------------------------------------------------+
|newline	  End of command					|
|space		  End of word						|
|tab		  End of word						|
|!		  History						|
|#		  Comment						|
|$		  Variable						|
|&		  End of command arguments, launch in background	|
|(		  Start sub-shell					|
|)		  End sub-shell						|
|{		  Start in-line expansion				|
|}		  End in-line expansion					|
||		  End of command arguments, Pipe into next command	|
|<		  Input Redirection					|
|>		  Output Redirection					|
|*		  Multi-character Filename expansion (a.k.a. globbing)	|
|?		  Single-character Filename expansion (a.k.a. globbing) |
|[		  Character Set Filename expansion (a.k.a. globbing)	|
|]		  Character Set Filename expansion (a.k.a. globbing)	|
|;		  End of command					|
|'		  Strong quoting					|
|"		  Weak quoting						|
|`		  Command substitution					|
|		  Sometimes Special					|
+-----------------------------------------------------------------------+

If you do not want one of these characters to be treated as a meta-character,
you must quote it. Another term for this is
, as in
“escape the normal behavior.” The Bourne shell has a predictable behavior for quoting meta-characters:

  1. Put a backslash before each character.
  2. Put single quotes around all of the characters.
  3. Put double quotes around all of the characters.
    Exceptions: the dollar sign ($) and back-quote (`) are special, but
    a back-slash before them will escape the special connotation.

    The Bourne shell has an internal flag that specifies when
    quoting occurs. It is either on or off. If quoting is on, then meta-characters
    are escaped, and treated as normal.
    The C shell is similar, yet not identical.
    As you will see, the quoting mechanism is less predictable.
    In fact, it has some maddening exceptions,
    Let me elaborate.

If you want to use a meta-character as an ordinary character, place
a backslash before it. To delete a file called
“a b” (there is a space in the filename between a and b),
type

rm a\ b

The second method for quoting meta-characters is specifying a string
that begins and ends with single quotes:

rm ‘a b’

In the Bourne shell, any character in single quotes is not a meta-character.
This is not true in the C shell. There are two exceptions: the exclamation
point, and new line.
The Bourne shell allows this:

echo ‘Hello!’

The C shell requires a backslash:

echo ‘Hello!’

The exclamation point is a meta-character, and the C shell uses it for its
and
features, which I will discuss later.
The other exception is a new-line character.
The Bourne shell allows:

echo ‘New line ->

The C shell requires a backspace before the end-of-line:

echo ‘New line ->

A novice programmer may consider this a feature, as any command with an
unterminated string will generate an error. However, when your programmer skills
increase, and you want to include a multi-line
script
in a shell script, the C shell becomes awkward.
Sometimes
needs a backslash at the end of a line, so in the C shell, you would need
two backslashes:

#!/bin/csh -f
awk ‘{printf(“%st%st%sn”,
$3, $2, $1}’

Click here to get file: CshAwk.csh
An
script in a C shell script is extremely awkward, if you pardon my
choice of words.

The last quoting mechanism is a string that starts and ends with the
double-quote marks:

rm “a b”

This is similar to the single-quote form, but it intentionally
escapes most meta-characters except the dollar sign and back-quote.
This allows command substitution, and variable interpretation:

echo “I am $USER”
echo “The current directory is `pwd`”

Like the single quoted string, the exclamation point is an exception:

echo “Hello!”

I usually call the single quote the
“strong” quote, and the double quote the
“weak” quote.
However, it is not so simple.
The frustrating thing about the C shell is that inside a double-quote string,
you cannot place a backslash before a dollar sign or back-quote to
escape the special meaning.
That is, when I execute the command

echo “$HOME”

the shell echoes

/home/barnett

So the backslash only works
some of the time.
The C shell if filled with special cases. You have to learn them all.
To make it easy for you, here is a table
that explains all of the exceptions.
The first column is the meta-character.
The second column shows what is required to get the meta-character in a string
delineated by double quotes.
The third column corresponds to single quotes.
The last column shows what is needed when there are no quotation marks.

+--------------------------------------------------------------+
|	   Meta-character interpretation in strings	       |
+--------------------------------------------------------------+
|Meta-character	  "..."	       '....'	    no quotation marks |
+--------------------------------------------------------------+
|newline	  Requires    Requires    Requires 	       |
|space		  Quoted       Quoted	    Requires 	       |
|tab		  Quoted       Quoted	    Requires 	       |
|!		  Requires    Requires    Requires 	       |
|#		  Quoted       Quoted	    Requires 	       |
|$		  Impossible   Quoted	    Requires 	       |
|&		  Quoted       Quoted	    Requires 	       |
|(		  Quoted       Quoted	    Requires 	       |
|)		  Quoted       Quoted	    Requires 	       |
|{		  Quoted       Quoted	    Requires 	       |
|}		  Quoted       Quoted	    Requires 	       |
||		  Quoted       Quoted	    Requires 	       |
|<		  Quoted       Quoted	    Requires 	       |
|>		  Quoted       Quoted	    Requires 	       |
|*		  Quoted       Quoted	    Requires 	       |
|?		  Quoted       Quoted	    Requires 	       |
|[		  Quoted       Quoted	    Requires 	       |
|]		  Quoted       Quoted	    Requires 	       |
|;		  Quoted       Quoted	    Requires 	       |
|'		  Quoted       Impossible   Requires 	       |
|"		  Impossible   Quoted	    Requires 	       |
|`		  Impossible   Quoted	    Requires 	       |
|		  Quoted       Quoted	    Requires 	       |
+--------------------------------------------------------------+

The phrase
“Quoted” means the meta-character does not have a special meaning.
The phrase
“Impossible” means the meta-character always has a special meaning,
and cannot be quoted.
The phrase
“Requires ” says that a backslash is required to escape the special meaning.

The phrase “Quoted” means the meta-character does not have a special meaning. The phrase “Impossible” means the meta-character always has a special meaning, and cannot be quoted. The phrase “Requires ” says that a backslash is required to escape the special meaning.

To use the table, imagine you have a file with the same name as
a meta-character. Suppose the filename was
“?” (a question mark).
You have three methods of specifying the exact filename when deleting it:

rm “?”
rm ‘?’
rm ?

If the file had the name
“!” (an exclamation mark),
then the table states you always need a backslash:

rm “!”
rm ‘!’
rm !

Notice that some combinations
don’t work. That is, there is no way to place a single quote
inside a string delineated by single quotes.
Here comes the tough question.
Suppose you wanted to do the impossible.
How do you solve this problem?

Normally, having different quotes is convenient.
You can use one form of quote to contains the other form:

echo ” ‘ “
echo ‘ ” ‘

How can you place a quote within a quoted string, when the quote is
the same type? The simple answer? You can’t.
But there is a simple trick that can be used for all complex cases.
But it requires a different view of quoted strings. You see, they are not
really strings. Most programmers think a string is defined by the quotes
at the beginning and at the end. That is, you place quotes around the string, and insert
special characters in the middle to get around any tricky conditions.
This does not accurately describe a UNIX shell. There is no concept of
strings in the shell. Instead, the shell has an internal flag which
can be enabled and disabled ny the quote characters.
The following examples are all identical:

rm “a b”
rm a” “b
rm “a “b
rm a” b”
rm “a”” “”b”
rm “a”‘ ‘”b”

In some cases, the letters
“a” and
“b” are quoted. In other cases, they are not, because they do not need to
be escaped. The space, on the other hand, is always quoted in each
example above. The secret is understanding which characters
have to be quoted, and selecting the best way to quote them.

Now suppose you want to include a double quote inside a double quote?
You can’t. But you can switch the types of quotation marks at any
point.
The last example switches the quotation marks from double quotes to
single quotes. This same technique can be used to delete a file
with a double quote in the filename. Here are fours ways to do this:

rm ‘a”b’
rm a'”‘b
rm a”b
rm “a”‘”‘”b”

Here are some other examples:

echo “The date command returns ” ‘”‘ `date` ‘”‘
echo ‘Here is a single quote:’ “‘”

A common question is how to pass a variable to the middle of a string.
Suppose you wanted to write an
AWK script that printed out one column.
To print the first column is easy:

awk ‘{print $1}’

But this script always prints the first column.
To pass the column number to the script requires the same
techniques:

awk ‘{print $’$1′}’

This is hard to read, and you need a certain knack to become
accustomed to understanding it. Just scan from left to right, keeping
track of the current quote state, and which character was used to
enable the quote condition. After a while, it becomes easy.

This is my third tutorial on the C shell. This month, I will discuss
filename expansion, and globbing.

One of the primary functions of a shell is to provide
an easy way to execute commands, and passing several files to the command.
Before the shell determines which command to execute, it
evaluates variables, and performs filename substitutions.
This is a fancy way of saying you can abbreviate filenames.
The Bourne shell only supports globbing.
The C shell supports three forms of filename substitutions:
globbing, in-line expansion, and
home directory expansion:

The first UNIX shell was called the Mashey shell. This was before the C shell
and Bourne shell was written. The Mashey shell didn’t have filename substitution.
If you wanted to list every file in a directory, the shell did not support

ls *

Instead, you had to use the
command:

ls `glob *`

Glob is a precise, scientific term that is defined as
“a whole messa,” which is not to be confused with
“glom” which means
“view” or “examine.”
An example would be
“I wanna glom a whole messa files.” The proper terminology, used by those with a doctorate in computer science,
is of course
“I wanna glom a globba files.” And anyone with a similar doctorate will know exactly what this means.
Try this at your next dinner party, and you too can impress the
neighbors.

Needless to say, after creating, editing, printing, and deleting globs of
files day after day, someone realized that life would be easier if the shell
did the globbing automatically. And lo, UNIX shells learned to glob.

The C shell has this feature of course.
The easiest way to learn how globbing works is to use the echo command:

echo *

This will echo every file in the directory. Well, not every one.
By convention, files that start with a dot are not echoed.
If you want to list all files, use

echo * .*

In other words, the dot must be explicitly specified.
The slash
“/” must also be matched explicitly.
Other utilities, like
, use this same convention.
The asterisk matches everything except these two characters, and means
“zero or more characters.” Therefore

echo a* b* c*

will echo all files that start with an
“a,”
“b,” or
“c.” Note that the shell sorts the files in alphabetical order.
But each expansion is sorted separately.
If you executed

echo c* b* a*

the order would first be the files starting with c, then with b, then with a.
Within each group, the names would be sorted.
Also note that the shell puts all of the files on one line.
The echo command can be used as a simple version of the
command.
If the
command is given the above command, it will sort the filenames
again, so they will be in alphabetical order.

If you want, you can enable or
disable globbing.
The command

set noglob

disables globbing, and

unset noglob

enables it again.
These two echo statements do the same thing:

set noglob
echo a* b* c*
echo ‘a* b* c*’

Both echo the string
“a* b* c*” instead of expanding to match filenames.

What happens if you type the command

echo Z*

and you have no files in your directory that start with a
“Z?” The Bourne shell will assume you know what you are doing, and
echo
“Z*” without any complaints.
Therefore if you have a Bourne shell script, and
execute

myscript Z*

then the script
will get the argument
“Z*” instead of a list of filenames.
The C shell gives you a choice.
If
none of the filename substitutions find a file, you will get an error
that says:

No match

But if you set the
“nonomatch” variable:

set nonomatch

then the C shell behaves like the Bourne Shell.

You should also note that the asterisk can be anywhere in a filename,
and you can use any number of asterisks. To match files that have the
letters a, b and c in sequence, use

echo *a*b*c*

The meta-character
“?” matches a single character.
Therefore

echo ???

will match all filenames that have three letters, while

echo ???*

will match files that have three or more letters.

You can match combination of characters, using square brackets.
If any of the characters inside the square brackets
match the single character in the filename, the pattern with match.
You can also specify a range of characters using a hyphen.
Therefore the following are equivalent:

echo a* b* c*
echo [abc]*
echo [a-c]*

To match any file that starts with a letter, you can use any of
the following:

echo [a-zA-Z]*
echo [abcdefghijklmnopqrstuvwxyzA-Z]*
echo [ABCDEFGHIJKLMNOPQRSTUVWXYZa-z]*
echo [zyxwvutsrqponmlkjihgfedcbaA-Z]*
echo [A-Zzyxwvutsrqponmlkjihgfedcba]*

As you can see, the order doesn’t matter, unless a hyphen is used.
If you specify a range in a reverse alphabetical order,
the results are unpredictable. The command

echo [c-a]*

will only match files that start with
“c” using the C shell, while the Bourne shell
will match files that start with
“c” or
“a.” Use improper ranges, and the different shells give different results.
The command

echo [c-b-a]*

will only match files that start with a
“c” with the C shell, while the Bourne shell will match files that start
with a, b or c. Apparently the Bourne shell will treat strange range
values as individual characters, while the C shell ignores bogus
ranges, except for the starting character.

You can combine these meta-characters in any order.
Therefore it makes sense to pick filenames that
are easy to match with meta-characters.
If you had ten chapters in a book, you don’t want to name them

Part1.bk Part2.bk … Part10.bk

You see, if you specified the chapters like this:

ls Part?.bk Part10.bk

the shell would expand all of the meta-characters, and then pass this to the
command, which would then change the order.
Therefore after file
“Part1.bk” would be
“Part10.bk” followed by
“Part2.bk.” Instead, use the names

Part01.bk Part02.bk …Part10.bk

so the alphabetical order is always the logical order.
This can be very useful if you have log files, and use the current
date as part of the file name.

It is also important to note that the shell evaluates variables
before expanding filenames.
So you can specify

echo $USER??.out

and the shell will first evaluate the variable
“USER,” (to
“barnett” in this case)
and then perform the filename substitution, matching files like
“barnett12.out” and finally sorting the filenames in alphabetical order.
Then the list of filenames is passed to the
command.

The C shell has a unique feature, in that it can generate patterns of
filenames even if they don’t exist.
The curly braces are used, and commas separate the pattern.
Suppose you have the file
“b0” in the current directory. The command

echo b[012]

will only echo

b0

But the command

echo b{0,1,2,3,0}

will generate

b0 b1 b2 b3 b0

Notice that the order is
not sorted alphabetically.
Also note that
“b0” occurs twice. If we change this to

echo [b]{0,1,2,3,0}

the output again becomes

b0

The in-line expansion comes first, and then the filename substitution
occurs.
You can put meta-characters inside the curly braces. The following
two are equivalent:

echo b* b?
echo b{*,?}

The number of characters can change within the commas.
These two commands are equivalent:

echo A1B A22B A333B
echo A{1,22,333}B

This in-line expansion has a multiplying effect.
The command

echo {0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}

will print out 100 numbers, from 00 to 99.
The Bourne shell does not have this feature.

The last for of filename expansion is the
“~” character. By itself,
it expands to the build-in variable
“home.” You can also provide a username. This allows you to specify
a filename in someone’s home directory, without knowing what it is:

more ~smith/.login

The C shell determines this value by examining the password file.

An essential part of understanding the C shell is mastering variables
and variable lists. Setting variables are simple:

set myvariable = word
set myvariable = “a string”

The second form is necessary if spaces are needed inside the variable.
I always put spaces around the equals sign, as the C shell seems to
complain less with extra spaces.
To clear a variable, set the variable to an empty string:

set myvariable = “”

to remove a variable, so it is no longer defined, use the
command

unset myvariable

If you create your own shell script, you can pass parameters
similar to the Bourne shell. The C shell even uses the same
convention of $1 and $*:

#!/bin/csh
echo First argument is $1, second argument is $2
echo All of the arguments are $*

Click here to get file: Csh1.csh
However, there is no $# variable, which returns the number of arguments in the
Bourne shell.

How can you check the number of arguments?
The C shell has a second way of specifying
the arguments passed to the shell script, using a predefined variable
list, called
“argv” The C shell borrowed this concept from the
C programming language. Wonder why? (Hint: it is called the
“C” shell for a reason.)
The value $argv[1] is equivalent to $1, and $argv[2] is the same as $2.
Furthermore, $argv[*] is equivalent to $*. The variable $#argv contains the number of
arguments passed to the shell:

#!/bin/csh
echo There are $#argv arguments
echo First argument is $argv[1], second argument is $argv[2]
echo All of the arguments are $argv[*]

Click here to get file: Csh2.csh
There is a subtle difference between $2 and $argv[2].
If there is only one parameter,
the line

echo Second argument is $2

will print

Second argument is

while

echo Second argument is $argv[2]

will generate an error, and print

Subscript out of range

The C shell has a mechanism to prevent this error.
It is also used to specify a subset of the list of values:

echo All of the arguments but the first are $argv[2-$#argv]

This does not generate an error.
With typical UNIX terseness, the above can be replaced with either of the two
following statements:

echo All of the arguments but the first are $argv[2-*]
echo All of the arguments but the first are $argv[2-]

This is a general purpose mechanism, as any value can be used to specify the
range:

echo first through third arguments are $argv[1-3]

If you specify a specific range, the argument has to be there.
That is, $argv[2] will generate an error in the second argument does not exist.
$argv[2-] will not.
If the first range is missing, the default is 1, or the first parameter.

Variables are allowed inside square brackets.

set first = 1
set last = $#argv
echo first argument is $argv[$first]
echo last argument is $argv[$last]
echo all of the arguments are $argv[$first-$last]

As you can see, the C shell allows you to easily specify
portions of the argument list using ranges of values.
This can be very convenient. Apparently the author of the C shell agreed,
because any variable can be an array list.
The simplest way to create an array list is to use the backquote characters:

set mydate = `date`
# returns a date, like
# Tue Jan 7 17:26:46 EST 1997
echo Month is $mydate[2], year is $mydate[$#mydate]

The Bourne shell has an array list, but only one, and it doesn’t have a name.
It is the argument list, which is set when the script is called. You can
change this with the
“set” command.
You must, however, remember to save the current values if you want to
use them again.
So if you need to manage several arrays,
and perhaps use one index to access several arrays,
the C shell might make the task easier.
Yes, I realize some consider my statement blasphemous.
Today, I’m wearing my
“Don’t bug me because I’m using the C shell” pin, so I don’t care. If you want to give me grief, read my
“Curse of the C shell” column three months ago.
I’m not going to sugar coat the C shell beast.
It’s covered with warts, but it does have some convenient features.
Just watch out for the warts. Speaking of which…

The C shell does not elegantly handle variables that contain spaces.
There is no equivalent to the $@ variable.
Consider this:

set a = “1 2 3”
set b = $a

Any sane person might expect that variables
“b” and
“a” have the same value. Surprise! This doesn’t work in the C shell.
On some versions of SunOS, the variable
“b” is empty.
On other systems, you get
“set: syntax error.”

How can you copy an array?
The command below should work, but doesn’t:

set copy = $argv[*]

It behaves like the example above. Unpredictable.
If you enclose the variable in double quotes, like this:

set copy = “$argv[*]”

then all of the parameters are in $copy[1], and $copy[2]
is not defined. A slight improvement.
The C shell has a special mechanism for specifying arrays, using parenthesis:

set copy = ( $argv[*] )

Therefore the following two statements are equivalent:

set mydate = `date`
set mydate = ( `date` )

The parenthesis is preferred for several reasons.
The following commands do not work:

set c = $*
set c = $argv[*]
set c = a b
set c = “a” “b”
set c = `date` `date`
set c = `date` $a “b c”

Some do nothing. Some generate an error.
Some cause a core dump.
Life would be dull without the C shell.
However, adding parenthesis
solves almost all of the problems:

set c = ( $* )
set c = ( $argv[*] )
set c = ( a b )
set c = ( “a” “b” )
set c = ( `date` `date` )
set c = ( `date` $a “b c” )

This eliminates the unpredictable behavior.
The only problem left is spaces inside variables. Since there is no
$@ variable, the only way to retain spaces in an array
is to copy each element over, one by one:

set b[1] = “$a[1]”
set b[2] = “$a[2]”

This, by the way, uses a special for of the
“set” command, that can modify a single array element.
However, the array must exist first, so the code to copy
an array is complicated, and darn ugly too.

In general, the C shell is not suited for variables that contain spaces.
Also, if there is any possibility that an argument contains a space,
you should use

set a = ( $argv[1] )

or

set a = “$argv[1]”

instead of

set a = $argv[1]

Alternately, just tell anyone who uses spaces in arguments to
perform an impossible biological act. I’ve learned this from my
colleges, who’ve come to the conclusion that anyone who worries about
spaces inside arguments is someone who has way too much free time.
I don’t know anyone like that, however.

The command:

set a = “”

Defines variable $a[1],
and sets it to an empty string.
$#a is equal to 1.
However, the command

set a = ()

empties the array, so variable $a[1]
does not exist.
The variable $#a is equal to 0.
The command

unset a

removes the definition of the variable.

The Bourne shell lets you refer to variables that do not exist.
If you ask for the value, you will get an empty string.
The C shell will give you a warning if the variable does not exist, or the
array element does not exist.
Using $1 instead of $argv[1] can help,
as well as using ranges, like $argv[1-].
There is another method, by using the special variable
$?x, where x is the name of the variable.
If the variable does not exist, it will have the value of zero.
If the variable exists, it will have the value of one.
You can combine this with an
“if” statement, which is somewhat more cumbersome than the Bourne shell technique.

The special command
“shift” can be used to remove the first array element. It
“pops” the first value of the stack of the argument list.
The
“shift” command can take an optional variable:

set a = ( a b )
shift a
# same as
# set a = ( b )

If you listen carefully, you can hear a slight noise as each variable
pops off the stack.
I’ve suddenly realized I’ve been working too hard.
I’ll continue next month. Until then, take care.

We’ve been talking about variables, lists, and strings.
Time to start doing something useful with the C shell.
Let’s start with a simple
way to branch.

myprogram && echo The program worked

If the program
“myprogram” has no errors, the script echoes
“The program worked.” In other words, if the program
“myprogram” exits with a status of zero, the
“echo” program is executed.
If any errors occur, the program would exit with a positive value,
which typically indicates the error that occurred.
To test for an error, use
“||” instead:

myprogram || echo the program failed

These can be combined:

myprogram && echo program passed | echo program failed

This can be used for many tests,
but there are some points to watch out for.
If the program
“myprogram” generates any output, it will be sent to standard output,
which may not be what you want. You can capture this by
redirecting standard output:

myprogram >/dev/null && echo program passed

If the program might generate an error, you can capture this
by using the special combination
“>&.” This merges standard error with standard output:

myprogram >& /dev/null && echo program passed

This type of conditional operation can be enclosed in parenthesis
to keep standard input flowing through the different programs.
For instance, if you wanted to test standard input for the word
“MATCH,” and either add the word
“BEFORE” if the match is found, or add
“AFTER” if no match is found, you can use the following ugly code:

#!/bin/csh
tee /tmp/file |
( grep MATCH /tmp/file >/dev/null &&
( echo BEFORE; cat – ) || ( cat – ; echo AFTER) )
/bin/rm /tmp/file

Click here to get file: prog.csh
If you save this script in a file called
“prog” and type

echo MATCH | prog

the script will echo

BEFORE
MATCH

If instead you execute

echo no | prog

the script will output

no
AFTER

The parenthesis are necessary, because
the
“echo” command does not read standard input. It discards it.
Putting parenthesis around the
“echo” and
“cat” commands connects the pipe to the input of both programs.

The C shell has some similarities to the Bourne shell.
In fact, the above script could be a Bourne shell script.
The two shells act the same in this case.
However, early versions of the C shell had a bug.
The meaning of
“&&” and
“||” were reversed. This was a long time ago,
and I think most versions of the C
shell have this bug fixed. Still, it may not be portable.
The second difference between the shells is the Bourne shell
allows the curly braces to be used as well as the parenthesis.
The parenthesis causes an extra shell to be executed. So the script
above requires 4 shells to be executed. The Bourne shell could do it with
one shell process. Still, I find it amusing that the above script
works for both the C shell and the Bourne shell. But I don’t get out much.

The second mechanism for doing tests in the C shell uses the
“if” command. There are two formats, a short form and a long form:

# first the short form
if ( )
# then the long form
if ( ) then

endif

The expression is a numerical expression. If the results is zero,
the expression is false. If non-zero, the expression is true.
These three statements will all output
“yes:”

if (1) echo yes
if (-1) echo yes
if (2) echo yes

If you want to use a program in the
“if” statement, similar to the
“&&” test, it can be placed in back quotes. I’ll use
the long form of the
“if” statement:

if ( `myprogram` ) then
echo yes
endif

In this case, the exit status of the program is not used.
Therefore, the only output from these statements is one
“yes,” while the other commands do not print:

if (`echo`) echo no
if (`echo 0`) echo no
if (`echo “”`) echo no
# Only the next statement is true:
if (`echo 1`) echo yes

This might strike you as inconsistent, and you would be right.
The Bourne shell uses the
“test” program to convert numbers and strings into status.
The
“&&” and
“||” commands also use the status to branch, in both the C shell,
and the Bourne shell.
The
“if” command does not use status.
Assume I created a script, called
“myexit,” that was simply this:

#!/bin/csh
exit $*

Click here to get file: myexit.csh
The following expressions would be true:

true && echo yes
myexit 0 && echo yes
if (1) echo yes

This is confusing, but the trick is to remember that
zero is true in the exit status, while non-zero
is true in expressions.
There is a way to get the exit status inside an expression.
It’s not a common technique, however.
The solution is to enclose the command inside curly braces.
If the command within curly braces
is successful (status of zero), then the expression is 1, or true:

if ( { myprogram } ) echo myprogram worked

However, if you try to redirect standard output, it will
not work:

if ( { grep pattern file >/dev/null } ) echo found pattern

This only tests for no errors. Most of the time people use the special
variable
“$?” which contains the actual error number found.

The short version of the
“if” command without a
“then” statement only takes one statement.
You cannot use parenthesis to add additional commands.
The following statement generates an error:

if (1) (echo a;cat) # an error

The
“then” word must be included to allow multiple statements.
If you have the longer form, you can optionally add
“else” and
“else if” commands:

if ($debug) then
echo debug mode
else if ($verbose) then
echo verbose mode
else
echo “normal mode”
endif

Any number of
“else if” statements can be used, including none.

The C shell has many problems with the
“if” command, that the Bourne shell does not have.
At first, the C shell seems adequate, but
when you try to accomplish something difficult, it
may not work.
I’ve already mentioned:

if (1) (echo a;cat) # an error

The solution is to use the long form, with the
“then” word.

Suppose you wanted to optionally empty
a file, removing all contents.
You might try the following:

if ($empty) echo “” >file

However, this does not work as expected. The file redirection is
started before the command is executed, and before the value
of the variable is determined. Therefore the command always
empties the file. The solution is again, to use the long form.

You can nest
“if” statements inside
“if” statements, but combining long and short forms
doesn’t always work. Notice a pattern?
I personally avoid the short form, because if I add an
“else” clause, or a nested
“if” statement, I get a syntax error.

The next problem is more subtle, but
an indication of the
parsing done by the C shell.
The commands that deal with flow control
must be the first command on the line.
As you recall, the Bourne shell specifies commands have to be on
a new line, but a semicolon works as well as a new line.
The C shell
requires the command to be the first word.
“So what?” you may ask. You may have never experienced this problem, but I have.
Try to pipe something into a conditional statement.
The C shell won’t let you do this without creating another script.

The second command used for flow control is the
“while …end” command.
This statement will execute the statements inside the loop
while the condition is true.
I often type the following in a window to examine a print queue:

while (1)
lpq
sleep 10
end

This command runs until I press control-C.
“While”” and
“end” must be the only words on the line.

As for problems, it’s hard to use the C shell to read a file one line
at a time.

The third command,
“foreach,” is used to loop through a list.
One common use is to loop through the arguments
of a script:

#!/bin/csh
# arguments are $*
foreach i ( $* )
echo file $i has `wc -l
end

Click here to get file: WordCount.csh
It can also be used with other ways of getting a list:

# remember the shell expands meta-characters
foreach file ( A*.txt B*.txt )
echo working on file $file
# rest of code
end

# here is another example
foreach word ( `cat file|sort` )
echo $word is next
# rest of code
end

The last flow-control command is the
“switch” statement. It is used as a multiple
“if” statement.
The test is not an expression, but a string.
The case statement evaluates variables, and
strings with the meta-characters
“*,”
“?,”
“[” and
“]” can be used. Here is an example that shows
most of these variations. It prints out the day of the week:

#!/bin/csh
set d = (`date`)
# like
# set d = ( Sun Feb 9 16:08:29 EST 1997 )
# therefore
# d[1] = day of week
set day2=”[Mm]on”
switch ( $d[1] )
case “*Sun”:
echo Sunday; breaksw
case $day2:
echo Monday;breaksw;
case Tue:
echo Tuesday;breaksw;
case Wed:
echo Wednesday;breaksw;
case Th?:
echo Thursday;breaksw;
case F*:
echo Friday;breaksw;
case [Ss]at:
echo Saturday;breaksw;
default:
echo impossible condition
exit 2
endsw

Click here to get file: GetDate.csh
The statements can’t be on the same line as the
“case” statement. Again, the
parser is the reason. The
“breaksw” command causes the shell to skip to the end.
Otherwise, the next statement would be executed.

The Bourne shell uses the program
to perform arithmetic.
It uses the
program to compare the results.
The C shell can both calculate complex expressions and test them
at the same time.
This provides simplicity, but there are penalties, which I will discuss later.
Table 1 shows the list of operators, in order of precedence. Operators in
the same box have the same precedence.

	+-----------------------------------+
	    |Operator	  Meaning		|
	    +-----------------------------------+
	    |(...)	  Grouping		|
	    +-----------------------------------+
	    |~		  One's complement	|
	    +-----------------------------------+
	    |!		  Logical negation	|
	    +-----------------------------------+
	    |*		  Multiplication	|
	    |/		  Division		|
	    |%		  Remainder		|
	    +-----------------------------------+
	    |+		  Addition		|
	    |-		  Subtraction		|
	    +-----------------------------------+
	    |<<		Bitwise shift left	|
	    |>>		Bitwise shift right	|
	    +-----------------------------------+
	    |<		Less than		|
	    |>		Greater than		|
	    |<=		Less than or equal	|
	    |>=		Greater than or equal |
	    +-----------------------------------+
	    |==		  Equal to		|
	    |!=		  Not equal to		|
	    |=~		  Pattern Match		|
	    |!~		  Pattern doesn't match |
	    +-----------------------------------+
	    |&		Bitwise AND		|
	    |^		  Bitwise OR		|
	    ||		  Bitwise inclusive OR	|
	    |&&		  Logical AND		|
	    |||		  Logical OR		|
	    +-----------------------------------+

The operators
“==,”
“!=,”
“=~” and
“!~” operate on strings. The other operators work on numbers.
The
“~” and
“!” are unary operators.
The rest require two numbers or expressions.
Null or missing values are considered zero. All results are strings,
which may also represent decimal numbers.
Table 2 shows some expressions, and the value after being evaluated.

		+--------------------------+
		|Expression	   Results |
		+--------------------------+
		|~ 0			-1 |
		|~ 1			-2 |
		|~ 2			-3 |
		|~ -2			 1 |
		|! 0			 1 |
		|! 1			 0 |
		|! 2			 0 |
		|3 * 1			 3 |
		|30 / 4			 7 |
		|30 % 4			 2 |
		|30 + 4			34 |
		|4 - 30		       -26 |
		|512 >> 1	       256 |
		|512 >> 2	       128 |
		|512 >> 4		32 |
		|2 << 4			32 |
		|3 << 8			768 |
		|4 < 2			0 |
		|4 >= 2			1 |
		|ba =~ b[a-z]		1 |
		|7 & 8			0 |
		|7 ^ 8			15 |
		|15 & 8			8 |
		|15 ^ 8			 7 |
		|15 ^ 7			 8 |
		|15 | 48		63 |
		|15 | 7			15 |
		|15 && 8		 1 |
		|15 || 8		 1 |
		+--------------------------+

The C Shell also supports file operators, shown in table 3.

+-----------------------------------------------------------+
|Operator      Meaning					    |
+-----------------------------------------------------------+
|-r filename   Returns true, if the user has read access    |
|-w filename   Returns true, if the user has write access   |
|-x filename   Returns true, if the user has execute access |
|-e filename   Returns true, if the file exists		    |
|-o filename   Returns true, if the user owns the file	    |
|-z filename   Returns true, if the file is empty	    |
|-f filename   Returns true, if the file is a plain file    |
|-d filename   Returns true, if the file is a directory	    |
+-----------------------------------------------------------+

If the file does not exist, or inaccessible, the test returns false.

If the file does not exist, or inaccessible, the test returns false.

Only two flow-control commands support complex expressions,
“while,” and
“if.” The
“exit” command also takes a complex expression.
This allows sophisticated passing of exit codes to a calling program,
but I’ve never seen a C shell script that makes use of this.
Surprisingly, the
“set” command does
not use complex expressions. If you execute the command

set a = ( 1 + 2 )

This creates a list of three elements, and $a[2] has the value of
“+.” There is a mechanism to assign complex expressions to variables.
A special command, called
“@” is used. You must have spaces after the
“@” character. Spaces are almost always required between all operators and expression
elements. The C shell likes spaces, and gets grumpy if you
don’t include enough. A vitamin deficiency, I guess.
The
“@” command also supports the
“++” and
“–” postfix operators,
which increment or decrement the variable specified.
This construct was taken from the C language.

Also borrowed from the C language is
the assignment operators +=, -=, *=, /=, and %=.
The expression

@ a %= 4

is the same as

@ a = $a % 4

Other examples of the
“@” command are:

@ a++
@ b=$a + 4
@ c*=3
@ c=4 + $b

Suppose you want to source a file, but are afraid that someone might
substitute it for another file. A crude example that checks if a file
is owned by you, and readable would be:

if ( -o $file && -r $file ) then
	source $file
endif

This example isn’t 100% secure, but it is slightly better than
blindly sourcing a file without checking who owns it.
Most of the time the file test operators are used to prevent runtime
errors caused by files that are not readable, or executable.

Notice the
command does not support complex expressions.
You can emulate the C language
construct using
. This code fragment counts up to 10 using a list:

foreach i ( 1 2 3 4 5 6 7 8 9 10 )
echo $i
end

However, if you wish to count to 100, this becomes impractical.
Here is how you can do it using complex expressions:

@ a = 1
@ MAX=100

# count from 1 to $MAX

while ( $a <= $MAX )
echo $a
@ a++
end

One stumbling block people discover is
looking for command line arguments. Suppose your script will
accept a
“-r” option.
However, the following line will not work:

if ( $argv[1] =~ -r ) echo found it

If the first argument is
“-r.” then this is evaluated as:

if ( -r =~ -r ) echo found it

The C shell will assume you meant to use a file operator, and test the
file
“=~” to see if it is readable. Then it sees the next operator,
which is again a
“-r,” but in this case there is no filename afterwards. This generates a
syntax error. The solution is to place a dummy character before both
strings:

if ( X$argv[1] =~ X-r ) echo found it

In complex expressions, parenthesis can be used to alter the default
precedence in evaluation. To put it another way, when in doubt, use parenthesis.
Both expressions below do the same thing:

if ( $a + 2 > 5 ) echo yes
if ( ( $a + 2 ) > 5 ) echo yes

However, parenthesis have several jobs.
The context specifies how parenthesis are used.
This is where the parsing of the C shell shows some additional warts.
In these examples, the parenthesis are used to specify a list:

set i = ( a b c d e f g )
foreach i ( a b c d e f g )
echo $i
end

These show expressions:

if ( $x > 2 ) echo yes
while ( $x )
@ $x–
end

This is an example of creating a subshell:

(stty 9600;cat file) >/dev/printer

And this is an example of grouping:

@ x = ( ( $b + 4 ) & 255 ) << 2

And here is an example where the parenthesis have two different meanings:

if ( ( $b + 4 ) > 10 ) echo yes

I’ve tried to combine several of these uses into one statement, and
it generates errors. I’m not surprised.

The C shell has special
“escape” commands, used to exit from
“while” and
“foreach” loops.
The
command will escape out and terminate the loop.
The
command will go to the end of the loop, but cycle through again.
Here is a complete shell script that prints out the numbers
2, 4, 6 and 8, but it’s nothing to cheer about.

#!/bin/csh

foreach i ( 1 2 3 4 5 6 7 8 9 10 11 12 )

# if 9, exit
if ( $i == 9 ) break
# if odd, then don’t echo
if ( $i % 2 == 1 ) continue
# Even numbers only
echo $i
sleep 1
end
echo ‘Who do we appreciate?’
sleep 1; echo $USER
sleep 1; echo $USER
sleep 1; echo $USER
sleep 1; echo ‘Yeah!!!!!!’

Click here to get file: Cheer.csh
I think this covers most of the issues with complex expressions.
Let me know if you have any questions.

In my discussion of the C shell, I’ve described the good points and bad
points of the C shell. For those who are keeping score, the Bourne shell is
ahead 10 to 2. Why is the C shell so popular?
To explain this requires a short history lesson. Forgive me.

When I went to college in the early 70s, programming meant going to
the keypunch station and carrying around decks of punch cards. The
first time I used an interactive terminal, directly connected to a
computer, it was a
hard-copy device.
A popular interactive terminal at that time was the Teletype.
It had a keyboard, and printed on a ugly roll of yellow paper.
Some models supported a paper tape reader and paper tape punch.
It was a bargain, because one machine was a terminal, printer, and backup
device. A complete I/O system in one unit, for less than $10,000!

We had a programmer whose job was to edit
paper tapes, punching new holes, and splicing paper.
The only device used was a Teletype and a tape splicer.
If a mistake was made, the
“programmer” would position the paper tape just right, and punch out all of the holes
to erase that letter. In case you wondered, this is why the ASCII code for
delete is 11111111 in binary. Each
“1” corresponds to a hole, and a row of 8 holes corresponded to
a deleted character. If you made a mistake, you could
“erase” the mistake without starting a brand new tape. Just back up and punch
out the error.
We felt fortunate when the boss ordered several video terminals,
which cost more than a complete PC system nowadays.
Editing was done by the terminal, which had memory, and keys with arrow
characters. We were truly excited. With our new program, that only
worked with our new terminal, and 64K of RAM, and 5 MB of hard
disk, we now had a
real computer system.
I imagine Berkeley had computers of a similar configuration, and
was equally excited when they got their first VAX. Trouble was,
the default editor,
, was designed for those old-fashioned hard copy terminals.
has a consistent user interface.
If you typed something right, it said nothing.
If you typed something the program
didn’t understand, it printed out a single question mark. The authors felt
that this was sufficient information, and the interpretation
of the error message should be obvious.
Nowadays people comment on this statement as proof that UNIX
was not originally user-friendly.
Wrong!
You see, Teletypes were incredibly loud.
Teletypes were also incredibly slow.
I remember pounding on the keys on a model 33 Teletype.
Pounding is the right word. I imagine martial-art students practiced
on the keyboard, in their effort attempt to develop strong-as-steel fingers.
Alas, I lacked the skill,
and the instant I made a mistake, the Teletype let loose a
70 decibel machine-gun rat-a-tat-tat for 5.7 seconds, as it typed
“Syntax error, please type command again – you stupid person.” Needless to say, this irritated me immensely. When I am irritated, I make mistakes.
If the operating systems I used only printed a question mark, the years of
electro-shock therapy might not have been necessary.

There must be a better way. There was. Bill Joy
decided the standard editor sucked, and wrote an editor that
did not require special hardware, and
allowed you to see what your file looked like
while you were editing it.
It was a WYSIWYG editor for ASCII characters.
He wrote a library
called
to go along with his
editor.
Most people forget what a major breakthrough this was.
Going through my 1980 edition of the Berkeley UNIX manual,
I see that Bill Joy wrote the
Pascal interpretor and compiler, along with
,
,
,
,
,
,
,
,
,
, and the Pascal modifications to
and
. He also wrote a significant part of the virtual memory, demand paging,
and page replacement algorithm for Berkeley Unix.

Bill Joy also wrote the C shell.
Twenty years later it’s easier to find fault in the C shell,
compared with current shells. But at the time, the C shell
had many new ideas, and many still favor it for
interactive sessions. Several years elapsed before
the Korn shell was written. And several more years elapsed before it
or similar shells became commonly available.
I’d like to meet someone who feels they could have done a better a
better job that Bill, in the same conditions.

Enough ranting.

All shells support file redirection using
“program > file” and
appending to a file using
“program >> oldfile.” This only redirects standard output.
If you want to capture both standard output and error output,
the C shell has a simple syntax. Just add a
“&” to the angle brackets.
This also works with pipes.
A list of the different combinations follows:

+---------------------------------------------------------------+
|Characters	 Meaning					|
+---------------------------------------------------------------+
||		 Pipe standard output to next program		|
||&		 Pipe standard and error output to next program |
|>		 Send standard output to new file		|
|>&	 Send standard and error output to new file	|
|>>	 Append standard output to file			|
|>>&	 Append standard and error output to file	|
+---------------------------------------------------------------+

This is very simple, and takes care of 98% of the needs
of the typical user. If you want to discard standard output, an keep the
error output, you can use

(program >/dev/null) >& file

This is very simple, and takes care of 98% of the needs of the typical user. If you want to discard standard output, an keep the error output, you can use

This takes care of 99% of the cases.
It is true the Bourne shell is more flexible when it comes to
file redirection, but the C shell is very easy to understand.

One of the features the C shell has for new users is a special
variable that can prevent a user from
“shooting oneself in the foot.” Consider the following steps to create and execute a script:

vi script
chmod +x script
script > script .out

One small typo, i.e. the space between
“script” and
“.out,” and the script is destroyed.
Here is another example:

program1 >>log
program2 >>log
program3 >>log
program4 >>lag

Because of a typo in the last line, the information
is sent to the wrong log file.

Both problems can be prevented very easily. Just set the
variable:

set noclobber

In the first case, you will get an error that the file already exists.
The second will generate an error that there is no such file.
When the
“noclobber” variable is set,
“>” must only point to a new file, and
“>>” must only point to a file that already exists.

This seems like a great idea, but there are times when
this feature gets in the way.
You may want to write over an existing file.
Or you may want to append to a file, but don’t know
if the file exists or not.
If you want to disable this feature, type

unset noclobber

You may wish to keep this feature enabled, but disable it
on a line-by-line basis.
Just add a
“!” after the angle brackets.
This is like saying
“I really mean it!” Here are some examples:

# Create new file
program >out
# overwrite the same file
program >!out
# append to a file, even if it doesn’t exist.
program >>!log

The
variable also affects the
“>&” an
“>>&” combinations:

#capture error and standard output
program >&! file
program >>&! log

If you sometimes use the
variable, you have to change your style to use the exclamation
point when needed.
That is, when you want to append
to a file that doesn’t exist, or write to a file that may exist.
A complete list of all of the variations, and their meaning, is below.
Notice how the meaning changes depending on the
variable:

+--------------------------------------------------------------------------------------+
|Characters	  Noclobber	   Meaning					       |
+--------------------------------------------------------------------------------------+
||		  Doesn't Matter   Pipe standard output to next program		       |
||&		  Doesn't Matter   Pipe standard and error output to next program      |
|>		  Not set	   Send standard output to old or new file	       |
|>		  Set		   Send standard output to new file		       |
|>&	  Not set	   Send standard and error output to old or new file   |
|>&	  Set		   Send standard and error output to new file	       |
|>>	  Not set	   Append standard output to old or new file	       |
|>>	  Set		   Append standard output to old file		       |
|>>&	  Not set	   Append standard and error output to old or new file |
|>>&	  Set		   Append standard and error output to old file	       |
|>!		  Doesn't	   Send standard output to new or old file	       |
|>&!	  Doesn't Matter   Send standard and error output to new or old file   |
|>>!	  Doesn't Matter   Append standard output to old or new file	       |
|>>&!	  Doesn't Matter   Append standard and error output to old or new file |
+--------------------------------------------------------------------------------------+

A second modification that Berkeley made was to add the
“-i” options to the
,
and
commands. These options warned the user if a file was going to be
destroyed.
The C shell supported an alias feature that allows you to define new
commands. If you type

alias move mv

then when you execute the command
“move,” the C shell performs a substitution, and executes the
“mv” command.
The new options, along with the alias command, allowed new users to
specify

alias mv mv -i
alias cp cp -i
alias rm rm -i

and before any file is destroyed, the system would warn you.
If you define these aliases, and wish to ignore them, just place a
backslash before the command:

\rm *

This turns off the alias mechanism.

Since I’ve started talking about the C shell interactive features,
it’s time to discuss the start-up files, or files whose name starts
with a dot. The C shell uses three dot-files:

+-----------------------------------------------+
      |File	  Purpose			      |
      +-----------------------------------------------+
      | .cshrc	  Used once per shell		      |
      | .login	  Used at session start, after .cshrc |
      | .logout	  Used at session termination	      |
      +-----------------------------------------------+

To be more accurate, the .logout file is more like a
“finish-up” file, but I’ll discuss that shortly.

To be more accurate, the .logout file is more like a “finish-up” file, but I’ll discuss that shortly.

The
file is scanned, or more accurately sourced, every time a new shell starts.
The shell executes the source command on the file.
If a C shell script starts with

#!/bin/csh -f

or you explicitly execute a C shell script with

csh -f script

Then the start-up file is not executed.
Think of the -f flag as the fast option.
I recommend that every C shell script start with
the
“#!/bin/csh -f” option.
Without it, the C shell executes the
file. Remember – this is the user’s personal file.
My file is different from yours.
If I executed that script, it might not work the same as when you
execute the script.
A shell script that depends on the contents of the
file is likely to break when other users execute it: a bad idea.

It is important to understand when these files are sourced.
When you execute a program like
,
or
, The value of the
environment variable is used, and that shell is executed.
If the shell is the C shell, then the
file is sourced.
If you execute a remote command using
, the shell specified in the
file is used.
If this is the C shell, then
is used at the start of the process.

The second startup file is
the
file.
It is executed when the user logs onto a system.
These sessions are called a
shell.
Assuming you have specified the C shell as your default shell,
typing your username to the
“login:” prompt on a console, or using the
or
command, then this is a login shell,
and the
file is sourced.
Ever wonder how the shell knows this?
The mechanism is simple, but most people don’t know about it.
When the
program executes a login shell, it tells the program that the first
character of the program is a hyphen.
That is, if you execute
“-csh” instead of
“csh.” then you would be starting a login shell.
You can prove this by copying
or linking
to a filename that starts with a hyphen:

cd /tmp
cp /bin/csh -csh
-csh

Try this and see. If you execute
“csh.” the .cshrc file is read. If you execute
“-csh,” both the .cshrc and .login files are read.
A shell created in this fashion executes the
file first, then the
file.
Without the hyphen, just the
file is executed.

The last file the C shell executes is the
file. This only happens when the shell is a login shell.

Knowing when each file is used is very important
if you want to keep your account as efficient as possible.
People have a tendency to add commands to any file, or in some cases both files.
Finally the system behaves the way the user wants, and the changes
are kept where they are without understanding the whys and wherefores.
As always, I believe it providing tables, allowing you to look up
the exact behavior in each condition. This is a summary
of those actions:

+-----------------------------------------------------------------+
|Condition		     Files sourced			  |
+-----------------------------------------------------------------+
|Logging on the console	     .cshrc, then .login, finally .logout |
|rlogin system		     .cshrc, then .login, finally .logout |
|rsh system		     .cshrc, then .login, finally .logout |
|rsh system command	     .cshrc				  |
|csh filename		     .cshrc				  |
|csh -f filename	     -					  |
|C shell Script without -f   .cshrc				  |
|C shell Script with -f	     -					  |
|Starting a new shell	     .cshrc				  |
|Opening a new window	     .cshrc				  |
+-----------------------------------------------------------------+

There are a couple of problems people have with their start-up
scripts. Let me list them.

  1. Determining which commands are the ones you want to execute.
    You discover a useful setting, and want to add this feature to all sessions.
  2. Learning when you want to execute these commands.
    Does this feature need to be set once, or for every shell?
  3. Executing commands at the wrong time. Some people put
    “biff y” in their .cshrc file. This is wrong. It should be in the .login file.
  4. Learning when the two files are sourced, and in which order.
    Some people think the .login file is executed before the .cshrc file.
    This seems logical, because the .login file is executed during login,
    but it is wrong. The .cshrc file is always sourced before the .login file.
  5. Bloat.
    Don’t add commands without thinking of where they go.
    Placing commands and options in the wrong place, may be meaningless,
    and slow down your shell.

All of these problems confound the new C shell user.
So how can you distinguish between these different cases?
Well, the C shell sets various variables under different conditions.
The operating system also has variables, independent of the shell.
I’ll briefly describe the difference, and provide a template.

I mentioned earlier that you can check if a variable is defined by using
“$?” before the variable name. For example, if variable
“abc” is defined, then
“$?abc” has the value of 1.
The $prompt variable is defined when the C shell is in
interactive mode. However, when the shell executes a script,
the $prompt variable is undefined. Therefore if you have the code

if ( $?prompt == 0 ) then
# This is a shell script
else
# This is interactive
endif

If you set the prompt in your .cshrc file without
testing that variable, then you will be unable to distinguish between
interactive sessions and scripts.
Why is this important? I have a large number of aliases. How large?
I currently have about 300 aliases. You may or may not think this is large.
It is significant, however. I noticed by shell was taking longer and
longer
to execute scripts. When I started customizing my
C shell, I tried

if ( $?prompt ) then


# 300 lines later
endif

This does make the shell faster. However,
I found there are two problems with this.
As the number of aliases I had grew, it became harder to
remember the association between the if/then/endif commands, because they were
six pages apart.
Good coding style says we should keep modules short and easy to understand.
The other problem was a matter of efficiency.
Even though the shell didn’t have to execute the 300 lines of aliases,
it still had to read each line, looking for the
“endif” command. This slowed down the shell.
Therefore I currently use something like this:

if ( ! $?prompt ) exit
if ( -f ~/.aliases ) source ~/.aliases

This keeps my .cshrc file short,
and allows the shell to skip reading a large file when it doesn’t have
to.

A second important condition used to customize your shell session
is the current terminal. This is learned by executing the program
“tty.” This will either be a serial device, like
“/dev/ttya” or a pseudo terminal, like
“/dev/pts/1” or
the master console on the workstation, which is
“/dev/console.” Many users customize their shell, so that they automatically
start up a window system.
I often see something like the following in a .login file:

if ( “`tty`” =~ “/dev/console” ) then
# start up the window system
/usr/openwin/bin/openwin
endif

I place double quotes around the command. This is good practice,
because if the command ever fails, the variable will have an empty
string as a value. The double quotes prevent this from becoming a
syntax error.

There are two kinds of C shell variables: local and environmental.
Local variables are local to the current shell.
If a new shell is created, then it does not have these variables set.
You have to set them for each shell. The .cshrc file is used to set
local variables.

Environment variables are exported to all sub-shells.
That is, if you set an environment variable, and then create
a new shell, the new shell inherits the value of this variable.
Inherit is the essential concept. The child can inherit the traits of the parent,
but anything the child does to itself does not affect the parent.
If you specify an environment variable before you start up the window system,
then all new shells, i.e. all new windows, will inherit the environment
variables from the parent shell.
But if you set an environment variable to a different value in each window,
this has no effect on the parent process, which is your login shell.

You can set environment variables in your .cshrc file. However, this
is unnecessary, because any variable set in the .login file will be
inherited by all sub-shells. There are two reasons you need to set an
environment variable in the .cshrc file. The first is because you need
to customize it for each shell. Perhaps different windows have
different values. The second reason is that you need to look up
something, by executing a program, and want to optimize your shell, so
that this only has to be done once.
Suppose you wanted to learn what your current computer is called.
You could use the following test:

if ( “`hostname`” =~ “grymoire” ) then

endif

However, this executes the program
“hostname” in every shell. If you want to optimize your shell, then only do this
once. The logical place is to do this in your .login file.
But you may want to use this information for something that is set in
your .cshrc file. One way to solve this problem is to check for a
special environment variable, and if it is not set, then execute the
command, and set the variable. An example is:

if ( ! $?HOSTNAME ) then
setenv HOSTNAME `hostname`
endif

There are some other special cases. Many people perform different actions
based on the current terminal type. If you log onto a system with a device
local to the system, the terminal type is known.
If you use
or
to create an interactive session, the terminal type is communicated
to the remote system. If you use the
command, the terminal type is unknown, and must be determined somehow.
Once the terminal type is known, the user often customizes the keyboard
configuration. In particular, some characters, especially the delete
key, differs on different terminals. One terminal may have an easily
accessible backspace key, and another has a convenient delete key.
The command to modify this is the
“stty” command. The .login file typically adjusts this parameter, based on
the terminal type.

# if the terminal type is an HP terminal,
# change the delete character
if ( $TERM =~ “hp*” ) then
stty erase ‘^h’
endif

Here is a sample .login file:

# Sample C shell .login file
# Created by Bruce Barnett
# This file is sourced after .cshrc is sourced
# set up the terminal characteristics
if ( -f ~/.terminal ) source ~/.terminal
# define the environment variables
if ( -f ~/.environment ) source ~/.environment
# set search path
if ( -f ~/.path ) source ~/.path

# Start up window system, but first, learn the terminal type once
if ( ! $?tty ) then
set tty = `tty`
endif

# You may wish to start a window system
# Here is one way:

if ( “$TERM” =~ “sun*” && “$tty” =~ “/dev/console” ) then
# some people like to wait 5 seconds
# echo “starting window system in 5 seconds”
# sleep 5;

# By using ‘exec’, then when you exit the window system,
# you will be logged out automatically
# without the exec, just return to the shell
/usr/openwin/bin/openwin
# exec /usr/openwin/bin/openwin

# – any more window systems?
# elsif ( $TERM =~ “abc*” && “$tty” =~ “/dev/console” ) then
# start up another window system

endif

And here is a sample .cshrc file:

# Sample .cshrc file
# Bruce Barnett 
# This part is executed on the following occasions:
#	1. "rsh machine command"
#	2. "csh scriptname"
#	3. All scripts that start with #!/bin/csh (without -f)	
# Read the minimum .cshrc file, if there

if ( -f ~/.cshrc.min ) source ~/.cshrc.min

# if run as a script, then $?prompt == 0
# if run as a remote shell, then $?prompt == 0 && $?term == 0
# if $USER is not defined, then "~" doesn't have the proper value
#     so bail out in this case

if ( ! ( $?USER && $?prompt && $?TERM )) exit

# This is an interactive shell

#---Local variables
# examples:
#     set noclobber
#     set myvariable = "value"
#     set mylist = ( a b c d e f g)


#----aliases
if ( -f ~/.aliases ) source ~/.aliases

#----Searchpath
if ( -f ~/.path ) source ~/.path

Click here to get file:

Click here to get file: Cshrc1

An essential part of Shell Mastery is understanding what a searchpath
is,
and how to optimize it.
Following the principle of modularity,
most of the UNIX commands are separate programs. Only a few are built
into the shell.
This means you can change your shell, and still use 99% of the
commands without change.
These external programs may be scattered in dozens of directories.
When you ask for a command that the shell doesn’t understand, it searches
the directories in the order specified by the search-path, and executes
the
first command it finds with the name you specified.
And trust me on this, systems that do not behave consistently are bad
for your mental health.
I knew a programmer who was writing software for a system that
behaved unpredictably. He receives excellent care nowadays, but he
always asks me the same question.
“Two plus two is ALWAYS four, right?” Poor guy.
The world will never be safe for programmers until we eliminate
all non-deterministic systems.

The searchpath is stored in an environment variable
“PATH.” You set or change the Bourne shell PATH variable using commands like:

PATH=/usr/bin:/usr/ucb:/usr/local/bin
PATH=$PATH:$HOME/bin
EXPORT PATH

The C shell has a different syntax for setting environment variables:

setenv PATH /usr/bin:/usr/ucb:/usr/local/bin
setenv PATH ${PATH}:~/bin

Notice that the tilde can be used instead of $HOME.
The curly brace is necessary in this case, because the C shell
has the ability to perform
-like actions if a color follows a variable name.
The curly braces
turn this feature off. Without the braces, you would get a syntax error.
The braces could be added in the Bourne shell example above, but it
isn’t required.

The C shell has an alternate way to modify the searchpath, using
a list. Here is the same example as before:

set path = ( /usr/bin /usr/ucb /usr/local/bin )
set path = ( $path ~/bin )

The variable name is lower case, the syntax is the list form, and a
space is used to separate directories. The Bourne shell uses a colon
as a separator, and a blank value is used to indicate the current
directory. Since any number of spaces can be used as a separator,
something else must be used to indicate the current directory. The
period is used instead. This is logical, because
“.” refers to the current directory.
The following command:

set path = ( . $path )

specifies that the current directory is searched for commands before
all other directories.
Important! This is a security problem.
See the sidebar to fully understand the danger of this action.

It might seem confusing that there are two path variables, one in
upper case, and the other in lower case. These are not two different
variables. Just two different ways to set the same variable.
Change one, and the other changes.

Because the C shell uses a list, this allows some convenient
mechanisms to examine and manipulate the searchpath.
For instance, you can add a directory to the third place of a searchpath
using

set path = ( $path[1-2] ~/new $path[3-] )

Examining files in the searchpath is easy. Suppose you want to
write a simple version of the
“which” command. The C shell makes this an easy job:

#!/bin/csh -f
# A simple version of which that prints all
# locations that contain the command
if ( $#argv != 1 ) then
echo “Wrong number of arguments – usage: ‘which command'”
exit 1
endif
foreach dir ( $path )
if ( -x $dir/$1 ) echo $dir/$1
end

Click here to get file: Which.csh

Here is the same script using the Bourne shell:

#!/bin/sh
# A simple version of which that prints all
# locations that contain the command
file=${1:-“Wrong number of arguments – usage: ‘which command'”}
paths=`echo $PATH | sed ‘
s/^:/.:/g
s/:$/:./g
s/::/:.:/g
s/:/ /g
‘`
for dir in $paths
do
[ -x $dir/$file ] && echo $dir/$file
done

Click here to get file: Which.sh
As you can see, the Bourne shell is much more complicated.
Surprisingly, my measurements show the Bourne shell version is faster.
Well, I found it surprising. I expected the C shell version to be
faster, because it doesn’t use any external programs. The Bourne shell
version executes three additional processes because of the back
quotes.
Therefore four programs compete with one C shell script. And the C
shell still loses. Hmmm. Does this tell you something?

The system comes with a C shell script called
“which.” Not only does it find the first reference, but it reports if the
command is an alias. This is fine, but I prefer the above script,
because it tells me about all of the commands, and runs much faster.
I called it
“Which,” with a capital
“W,” so I can use either one.
The Korn shell has a build-in command, called
“whence.”

Most people specify their searchpath in their
“.cshrc” file.
But this really isn’t necessary. Like all environment variables,
all newly created shells get their environment from their parent.
Some people therefore specify it in their
“login” file.
All new shells will have this searchpath.
I set my searchpath before I start my window system.
This is very flexible, and quite easy to do.
Just create a shell script that specifies your new searchpath, and
then start up the windowing system. If you use OpenWindows,
an example might be

if ( ! $?OPENWINHOME ) then
setenv OPENWINHOME /usr/openwin
endif

set path = ( $path $OPENWINHOME/bin )

$OPENWINHOME/bin/openwin

If you want to add a new directory to your searchpath,
change it. If you then create a new window using a command
like
, or
, that window will inherit the searchpath from their parent.
I specify my searchpath in a file called
“.path.” It contains something like this:

set mybin = ( ~/bin )
set standardbin = ( /usr/ucb /usr/bin /bin )
if ( $?OPENWINHOME ) then
set winpath = ( $OPENWINHOME/bin )
else
set winpath = ( )
endif
# extra lines omitted
set path = ( $mybin $standardbin $winbin )

I start my window system like this:

#!/bin/csh -f
# start OpenWindows
setenv OPENWINHOME /usr/openwin
source ~/.path
$OPENWINHOME/bin/openwin

Click here to get file: OpenWin.csh
This way I have one place to change my searchpath for all conditions.
Any time I want to, I can define or undefine variables, and
source the same file to reset my path.
This allows me to use different windowing systems, or
different versions, and have one main file to control my search-path.

Another way I change my searchpath is with an alias.
You may want to define the following aliases:

alias .path ‘set path = ( . $path )’
alias poppath ‘set path = ( $path[2-] )’

The
“.path” alias adds the current directory, while
“poppath” removes the first one from the list.

You can make aliases as simple or as complicated as needed.
For instance, you can radically change your environment with the
simple

alias newstuff “source ~/.anotherpath”
alias newwin “source ~/.anotherpath;cmdtool&”

You can create multiple personalities, so to speak.

One of the simplest way to reset your path is to
type the new path on the command line.
If you have problems, you can always
change your
“.cshrc” file to have a precise path, or have it source the
“.path” file you created.
After this, all new shell windows you create will have the new path.
Another convenient way to undo the change is to execute another shell.
That is, before you experiment, type

csh

Then modify your searchpath. When done, type a Control-D.
This forces the current shell to terminate, and the environment
variables of the earlier shell are restored.

I’ve discussed several ways to change your searchpath.
As a summary, here are the methods:

  1. Explicitly set the path.
  2. Specify it in your .cshrc file.
  3. Specify it in your .login file, or before you start the windowing system.
  4. Specify it in another file, and source this file.
  5. Execute a shell script that changes the path, and then executes
    another program or shell.
  6. Use an aliases to do any or all of the above.

    No one method is right for everyone. Experiment. But don’t think you
    have to set your searchpath in your
    “.cshrc” file. Other solutions are possible. In fact, next month, I will
    discuss how to optimize your searchpath.

Some people put their current directory in their searchpath.
If you type

echo $path

and you see a dot, then you are vulnerable.
If you ever change directories to one owned by someone
else, you may be tricked to execute their commands instead of the ones
you expect.
Don’t believe me?
Okay. You’ve forced my hand.
Suppose I created a file called
“ls” that contains the following command:

/bin/rm $HOME/*

If I placed it in the
“/tmp” directory, then
as soon as you typed

cd /tmp
ls

all of your files would be deleted!

If you
must include the current directory in your searchpath, put it
at the end:

set path = ( $path . )

This is a little better, but you can still fall victim to the same trap.
Have you ever made a typo when you executed a command?
I could call the script
“mroe” or something similar, and still delete all of your files.
Now – are you willing to risk this?
I hope not. I tell people how dangerous this is. Remember, other
actions could be taken instead.

Personally, I don’t have the current directory in my searchpath.
It was painful at first, but I soon learned how to adjust.
When I want to execute a command in the current directory, I just type

./command

I do this when I debug the script.
When done,
I move the command into my private
“bin” directory:

cp command ~/bin

Is that so hard? I sleep much better at night.

Last month I discussed various ways to modify your C shell searchpath.
This month, I will discuss ways to optimize your path.

What do I mean by optimization?
Well, to tell the truth, I have looked at a lot of C shell start-up
files,
and I shudder at what I see. Some people have dozens of directories in
their searchpath. I also see people walking around with a gloomy
look, as if a storm cloud is circling over their head.

“What’s the matter?” I ask.

“My file server is down. I can’t get any work done.” they reply.

“Oh.” I reply.
“I didn’t notice.”

And it’s true. A server went down, and it didn’t bother me
at all because it wasn’t in my searchpath.
When some people
discover a directory that contains useful programs, they add it to
their searchpath. The searchpath grows and grows, until it becomes so
convoluted, no one understands it.
That’s the wrong thing to do.

You see, I created a special directory that contained symbolic links
to files on remote systems. Because the directory is on my local
workstation, I am not affected if a server goes down. The only time I
have a problem is if I use one of those executables. That process will
freeze, but only that process. All I have to do is create a new
window, and continue working.
I call this a cache dirctory, and I know that isn’t the best name for
it. A better name ought to be
“favored.” but what the heck.

I will admit that solving this problem isn’t trivial.
In fact, I wrote a program to help me figure out what to do.
Several programs, as it turns out. Let me describe them.

The first script, and the most important one
creates and maintains the cache directory.
If you want to use the directory
“/local/cachebin” as a cache directory, and want to eliminate the directory
“/public/bin,” just type

CreateCacheDir /local/cachebin /public/bin

This will look at all of the executables in
“/public/bin” and create a symbolic link to them in the
“/local/cachebin” directory.
You can then remove
“/public/bin” from your searchpath, and if the server providing this directory goes
down,
you will not be affected.
The script
follows:

#!/bin/sh
# Argument #1 is the directory where we will cache
# a filename. Actually, not a cache, but a link.
# where is the cache directory?
# Usage
# CreateCacheDir Cachedir dir1 [dir2 …]
# Function:
# – Create a symbolic link in cachedir, pointing to the files in dir1, etc.
#
CACHE=${1:?’Target directory not defined’}
if [ ! -d “$CACHE” ]
then
echo making cache directory “$CACHE”
mkdir $CACHE
fi

shift

# The rest of the arguments are directories to cache

verbose=false # true to see what happens
debug=false # true if you want extra information
doit=true # false if you don’t want to change anything

for D in $*
do
$verbose && echo caching directory $D
# list files, but ignore any that end with ~, or # or % (backup copies)
for f in `cd $D;ls|grep -v ‘[~#%]$’`
do
if [ -f $CACHE/$f ]
then
$debug && echo $CACHE/$f already exists
else
if [ -f $D/$f -a -x $D/$f ]
then
echo $D/$f
$verbose && echo ln -s $D/$f $CACHE/$f
$doit && ln -s $D/$f $CACHE/$f
elif [ -d $D/$f ]
then
$verbose && echo linking directory: ln -s $D/$f $CACHE/$f
$doit && ln -s $D/$f $CACHE/$f
else
$verbose && echo linking other: ln -s $D/$f $CACHE/$f
$doit && ln -s $D/$f $CACHE/$f
fi
fi
done
echo you can now take $D out of your searchpath

done

Click here to get file: CreateCacheDir.sh
This does the work, but how do you know which directories to replace?
I wrote some programs to measure how good (or bad) my searchpath is.
You might find them useful.

One way to simplify the searchpath is to identify directories that are
really symbolic links to other directories.
For instance, there is no reason to have both
/bin
and /usr/bin
in your searchpath, if one points to the other.
This script, called
, will identify these cases:

#!/bin/sh
# Find the unique and final location of a directory
# Usage:
# ResolveDir directoryname
#
# If the directory is called “.”, return “.”
dir=${1:?’Missing argument’}

[ “$dir” = “.” ] && { echo “.”; exit 0; }
cd $dir >/dev/null 2>&1 && { pwd; exit 0; }
exit 1;

Click here to get file: ResolveDir.sh
The next script, when given a directory, returns the system name on which the
directory resides.
If the file is on the local system, it returns the host name.
This script is called
.

#!/bin/sh
# Given a directory, return the system it is mounted on
# If it is localhost, then echo `hostname`
dir=${1:?’No directory specified’}
cd $dir

# On SunOS 4.x, use /usr/bin/df before /usr/5bin
# On Solaris 5.x, use /usr/ucb/df before /usr/bin
# Solve the problem by specifying the explicit path
PATH=/usr/ucb:/usr/bin:/usr/5bin:$PATH
export PATH

x=`df . | grep -v Filesystem`
# use expr to extract the system name
server=`expr “$x” : ‘(.*):’`
# with sed, I could do $server=`echo $x | sed ‘s/:.*//’`
if [ “$server” ]
then
echo $server
else
hostname
fi

Click here to get file: Dir_to_System.sh
Using these programs, I wrote some programs that evaluate my current
searchpath. Since I am talking about the C shell, I started to write
the script in this shell.
However, because of limitations of the C shell, I have to
split one script into three files. The main script,
, calls two scripts:

#!/bin/csh -f
# this could be one script instead of three if
# we were using the Bourne Shell
# But the C shell isn’t very good at piping
# commands inside of loops.
#
# Therefore we generate the pipe in one script,
# and feed AWK in another script
GetPaths | analyze_paths.awk HOSTNAME=`hostname`

Click here to get file: AnalyzePaths.csh
The script
Outputs one line for each directory in the searchpath.
Each line contains the directory name, the final name (if a symbolic
link) and the system that provides the directory:

#!/bin/csh -f
foreach p ( $path )
if ( -d $p ) then
set newp = (`ResolveDir $p`)
set server = (`Dir_to_System $p`)
echo “${p}:${newp}:${server}”
else
echo “${p}:?:?”
endif
end

Click here to get file: GetPaths.csh
The last script is a complex
script, but it outputs useful information.
For instance, it reports directories that don’t exist,
redundant directories, and specifies remote directories that can be
eliminated. For example, it could report

Directories that don’t exist on this system:
/local/bin/SunOS
/usr/etc
You are dependent upon the following systems:
server1, directories: /home/barnett/bin
Directory /usr/X11R6/bin used 2 times (symbolic links: 1)
symbolic links for ‘/usr/X11R6/bin’ are: /usr/X11/bin

The script is:

#!/usr/bin/nawk -f
# Do this before you read any input
BEGIN {
FS=”:”;
}

# do this for each line
(NF==3) {
if ($3 ~ /?/ ) {
# then it is a directory that does not exist
missing[$1]=1;
number_of_missing++;
} else if ( $1 ~ /./ ) {
# ignore it – it is the “.” directory
} else {
# count how many times each directory is used
used_count[$2]++;
# is it a duplicate,
if ($1 !~ $2) {
links[$2]++;
# remember it, by catenating two strings
used[$2] = used[$2] ” ” $1;
}

# Is it a remote system?
if ($3 !~ HOSTNAME) {
systems[$3]++;
# if this is the first time we have seen this directory
system_to_dir[$3] =
system_to_dir[$3] ” ” $1;
remote_systems++;
}
}

# printf(“%st%st%sn”,$1, $2, $3);
}
# Do this at the end of the file
END {
# Any directories that do not have to be included?

if (number_of_missing>0) {
printf(“Directories that don’t exist on this system:n”);
for (i in missing) {
printf(“t%sn”, i);
}
}

# how many computer systems are needed?

if (remote_systems) {
printf(“You are dependent upon the following systems:n”);
for (i in systems ) {
printf(“tsystem %s, directories: %sn”, i, system_to_dir[i]);
}

} else {
printf(“Good! You are not dependent upon any other servers,”);
for your current directoryn”);
printf(” except for your current directoryn”);
}

# What about duplicate directories?

for (i in used ) {
if (used_count[i]>1) {
printf(“nDirectory %s used %d times (symbolic links: %d)n”,
i, used_count[i], links[i]);
if (links[i]>0) {
printf(“tsymbolic links for ‘%s’ are: %sn”, i, used[i]);
}
}
}

}

Click here to get file: analyze_paths.nawk
There you go. Using these scripts will give you a set of tools to
improve your searchpath. Do it right, and may you never have your
workstation freeze again.

So far, I’ve explained how to optimize your searchpath.
But that is only part of the problem.
If you only used one computer, simplifying your searchpath would be
easy.
But logging onto many different computers makes life
“interesting,” as the ancient Chinese curse goes.
You could do what most people do, and keep adding directories
until every possible directory is in your searchpath.
Of course, as I explained last month, this makes your account as
stable as a one-legged elephant.
I have a solution, based on specific rules.
Here is the short list:

Understand directory characteristics.
Define a consistent naming convention.
Define a strategy.
Reduce the complexity.
Use local link/caching directories.
Consider a local home directory

Let me describe each of these rules.

The UNIX file system was designed to be the single common structure to
perform all operations. All input and output, all devices, and the
internals of the operating system are reachable by using special files.
With NFS, this was extended to include remote files, making them
look like local files, and making all file-based UNIX utilities
capable to operating on remote files.

However, all directories don’t have the same characteristics.
Here are some of the variations:

·
A directory that contains standard architecture-specific executables.
The directory is read-only, and identical on other systems of the same
architecture. Example: /usr
·
System-specific configuration files. Typically writable by
super-users only. Example: /etc
·
System-specific directory to hold temporary files. Writable by various
processes, programs, and users. Often not backed up. Not visible by
other systems.
Example: /var
·
Same as the above, but backed up frequently.
Example: /private
·
Common files shared across multiple groups.
Log onto other systems, and see the same files.
Example: /home/server/project
·
Directories which contain locally added executables.
This may be private to the system. Example: /local
·
Same as above, but containing executables that are shared among
several systems of the same architecture. Examples: /usr/local, /project/bin
·
Same as the above, but containing executables and/or data for multiple
architectures. Example: /public

As you can see, there are many different characteristics, and
every user has to understand the difference.
Make sure you understand how the files at your site are organized.
Most new workstations have lots of disk space, and it is rare that the
systems don’t make it available. Users should know if
the files are visible to other systems, and if the files are backed up
or not.

Some directories are project-related.
Executables are only used when working on the project.
Other directories, such as
“/projects/bin,” are used for certain rarely-used functions.
These are what I call
“optional” directories. If they are missing, you can still do other work.
Other directories are mandatory.

Some companies do not have a consistent naming strategy. This is a
serious problem. If the location of a single file changes when
different machines are used, then the user has to deal with this extra
complexity, which is very difficult, and if not taken care of, can
lead to irritability, moroseness, and eventually–insanity.
Sun’s automounter can help. For instance, you can set up a network so
that your home directory always has the same name, even if it is
moved to another system. Some sites also use a mechanism such as
“/work/” to specify the location of a project.
Another popular and practical convention is to specify
machine-specific files using a path that contains the name of the
machine.
If all machines use the same convention, then you can make sure the
“data” directory on computer
“server” is called
“/home/server/data” is the same directory on all machines.

You may want to write up your strategy. This helps
clarify some of the decisions. For instance, here is one similar to
what I use, leaving out the standard directories:

/home/ – Shared system-specific files. Backed up.
/work/ – Project directories.
/private – Local to system, not backed up, unless I do it myself.
/local – Local to current system. Not shared.
~/SunOS/5.5.1/sun4u/bin – Executables for a specific system type

The important directories are the last two, because these contain the
executables for my computer.
But deciding on a naming strategy is the first step.

It doesn’t matter what the convention is, as long as it is
consistent. But if it’s too complicated, errors can occur.
When possible, keep things simple.
Remove non-essential directories.
If you don’t need to use certain executables all the time,
then add them when you need them using an alias.
To repeat the lesson from two months ago, don’t set the path in your
“.cshrc” or
“.login” file. Inherit it from your environment. When you want to
add a directory, change your environment for that window.

Once you have removed all of the directories you use occasionally,
you still might have several directories that
are on other systems. What then?

The solution is simple. Create a directory on your local system, that
contains symbolic links to the real files.
Then remove the original directory from your searchpath, and add the
new one. I discussed this in detail last month.
But there is one more step.

Most large installations share user home directories.
No matter which system you log onto, you are in the same spot.
This is convention, but there are two problems.
The first concerns efficiency, and the second security.
The efficiency is a concern if the server providing this file goes
down.
The security is a concern, because anyone who can gain superuser
access
on any system that mounts that home directory, can break into that
account if you use
and have access to your files.
To solve both problems, create a directory on the local system that
has copies of some of the critical files, like
“.cshrc” and
“.login.” Since the
“.rhosts” file is not available to other systems through NFS,
A hacker cannot modify your
“.rhosts” file and log onto your workstation.
A better solution is to eliminate the
“rlogin” and
“rsh” services, using a program like
“ssh” instead. But that’s another topic.

Having a home directory local to your main computer can increase your
efficience, by removing the dependance on other systems.
You can have your own directory for
executables, for instance.

I’ll go through it a step at a time.
Remember, I do not recommend you always set your searchpath in your
“.cshrc” or
“.login” file.
Set it when you need it, like starting up a window system.
Assume the searchpath is controlled by a file called
“.path.” Here is my version of this file:

# example .path file

if ( -f ~/.path.default ) then
source ~/.path.default
else
# this is a default searchpath
set path = ( ~/bin /usr/ucb /usr/bin /usr/local/bin /local/bin )
endif

Click here to get file: Path1.csh
The system searches for a file called
“.path.default.” If this file is found, then it is used. Otherwise a default searchpath
is specified.
The file
“.path.default” is a bit more complicated, but it is designed to handle special cases
in a simple manner:

# .path.default modified for SunOS

if ( ! $?HOSTNAME ) then
setenv HOSTNAME `hostname`
endif

# get host specific path, if there
if ( -f ~/.path.$HOSTNAME ) then
source ~/.path.$HOSTNAME
endif

if ( ! $?SYSTEM ) then
set SYSTEM = “`uname -s`”
endif

# get system-specific searchpath, if there
if ( -f ~/.path.$SYSTEM ) then
source ~/.path.$SYSTEM
endif

# define these if .path.$SYSTEM doesn’t

# define the system defined paths
if (! $?SYSPATH ) then
set SYSPATH = ( /usr/ucb /usr/bin /bin )
endif

# define the places a window system’s files are located

if (! $?WINPATH ) then
set WINPATH = ( /usr/X11/bin /usr/X11R6/bin /usr/openwin/bin )
endif

# Private executables
if ( ! $?MYBIN ) then
set MYBIN = ( ~/bin ~/bin/$SYSTEM )
endif

# local to machine
if ( ! $?LOCALBIN ) then
set LOCALBIN = ( /local/bin /local/bin/$SYSTEM )
endif

#set CACHEBIN = ( $HOME/cachebin )
set CACHEBIN = ( )

#If TOTALPATH is defined, use it, else build it up from the pieces
if ( $?TOTALPATH ) then
set path = ( $TOTALPATH )
else
set path = ( $CACHEBIN $MYBIN $LOCALBIN $WINPATH $SYSPATH )
# set path = ( $CACHEBIN $MYBIN $LOCALBIN $WINPATH $SYSPATH . )

endif

Click here to get file: Path.default
There are many things to point out in this file.
First – let me describe the variables

HOSTNAME – The system hostname
SYSTEM – The operating system type
SYSPATH – The standard vendor-supplied directories
WINPATH – Directories used for the window system
MYBIN – Directories that contain my personal executables
LOCALBIN – Where extra executables are kept
CACHEBIN – My local cache directory

Suppose you are on a system called
“pluto.” If so, then the script searches for the file
“.path.pluto.” If this file is found, it is sourced.
This file can be quite simple.
For instance, if the file
“.path.pluto” contained these two lines only:

set SYSTEM = “FunnyUnix”
set TOTALPATH = ( ~/bin /usr/bin /usr/ucb /usr/local/bin )

Then the value of
will be used to set the searchpath.
No other programs will be executed.
The system doesn’t even need the
“uname” executable.

Here is another example, names
“path.neptune” for a computer called neptune:

set SYSTEM = “SunOS”
set MYBIN = ( ~/bin ~/SunOS/bin )

In this case, the file
“.path.SunOS” would be sourced, and the default values in that file would
specify the searchpath
The exception would be the value of
“MYBIN.” I have set up these files so that
each system can have it’s collection of paths that define the searchpath.
You can customize the directory used for the window system
on a particular machine, yet still add a common NFS directory to all
systems,
by modifying the value of $path near the end of the file.
Still, this doesn’t solve all cases.
In particular, SunOS 4.X and 5.X systems have different
searchpaths. Here is a file that shows one way to automatically
change the searchpath based on the version of the operating system:

# .path.SunOS
# copied from .path.default, and modified

if ( ! $?SYSTEM ) then
set SYSTEM = “`uname -s`”
endif

# Having this here would cause an infinite loop
# Make sure it is commented out
#if ( -f ~/.path.$SYSTEM ) then
# source ~/.path.$SYSTEM
#endif

# define these if .path.$SYSTEM doesn’t

if ( ! $?MACHINE ) then
set MACHINE = “`uname -m`”
endif

if ( ! $?REV ) then
set REV = “`uname -r`”
endif

# define the system defined paths
if (! $?SYSPATH ) then
if ( “$REV” =~ 4.[012].* ) then
set SYSPATH = ( /usr/ucb /usr/bin /usr/5bin /bin /usr/etc )
else if ( “$REV” =~ 5.[0-6].* ) then
set SYSPATH = ( /opt/SUNWspro/bin /usr/ccs/bin
/usr/ucb /usr/bin /usr/sbin )
else
# How did I get here?
set SYSPATH = ( /usr/ucb /usr/bin /bin )
endif
endif

# define the places a window system’s files are located
# I could look at DISPLAY, and change this depending on
# the value

if (! $?WINPATH ) then
if ( ! $?OPENWINHOME ) then
setenv OPENWINHOME /usr/openwin
endif
set WINPATH = ( $OPENWINHOME/bin )
endif

# define the places where architecture-specific binaries are
#
if ( ! $?MYBIN ) then
set MYBIN = ( ~/bin ~/$SYSTEM/$REV/$MACHINE/bin )
endif

if ( ! $?LOCALBIN ) then
set LOCALBIN = ( /local/bin )
endif

#set CACHEBIN = ( )
set CACHEBIN = ( $HOME/cachebin )

# If I set this,
# then the variables in .path.default will be skipped
#set TOTALPATH = ( $CACHEBIN $MYBIN $LOCALBIN $WINPATH $SYSPATH )

Click here to get file: Path.sunos
As you probably noticed, I used

~/$SYSTEM/$REV/$MACHINE/bin

as a directory for a machine-specific searchpath.
This becomes, when evaluated,

~/SunOS/5.5.1/sun4u/bin

You can move an executable there, and make links from other
directories to that file if you want to.
Other approaches also make sense. You could have a searchpath that
includes several directories in a particular order, such as the following:

~/bin
~/SunOS/bin
~/SunOS/5.5.1/bin
~/SunOS/5.5.1/sun4u/bin

The first one could hold all shell scripts.
The second one could contain all Sun specific shell scripts.
The third one could contain all executables for a Solaris 5.5.1
system. And the fourth directory can contain machine-dependent
executables.
Or you could use underscores instead of slashes:

set MYPATH = ( ~/bin ~/SunOS_bin ~/SunOS_5.5.1_bin )

I hope you find this setup easy to use, and easy to modify.
It is a bit complex, but it offers a lot of flexiability.
I hope you find it useful.

In ancient times, before mice existed, large beasts roamed the earth.
These included band printers, 9 track tape drives, (oddly 9-track was
before 8-track), and disk platters. The most fearsome of all the
beasts was the TeleType, able to cause piercing headaches. Quieter
machines evolved, like the Silent 700, and the DecWriter. A new beast
was seen wandering the dark and desolate laboratories. It was
quick. It was silent. It was the VKB, or Video Keyboard, a choice
morsel for those higher in the evolutionary plane i.e. the Hacker
(Hackerus Keyboardus).

A common sound was the stampede of fingertips, as the Hacker stalked
his or her prey – the perfect program. Faster, faster went the
fingers, but it was never fast enough. That perfect program was just
around the corner, but rarely was it caught.

One hacker, in an effort to go faster still, decided to enhance his
shell
in such a way that all he had to do was take a tiny step in a
direction, and the shell knew what he wanted to do.
That hacker added history. And thus was the history mechanism born.

Nowadays shells (like ) support a history mechanism that can
visually modify the command line, allowing the user to edit the
command line, call up previous commands by pressing the up arrow. The C shell
does not do this. It was designed for
any terminal, including the prehistoric hard-copy terminals.
The C shell has no problems running within
Sun’s , for instance.
To enable history, set the history variable:

set history = 100

This tells the shell to remember the last 100 commands.
You can make this number bigger or smaller. But the larger the number,
the more memory the shell uses.

The command
“history” will print out the history information.
If you specify a number such as 20, it will list the last 20 commands.
You can save a series of commands, and read them in later:

history -h 20 >file
… (do something else )
source -h file

The
“-h” option is used to make the format suitable for sourcing files.
The history command normally adds a number before each line for
reference.
The
“-h” turns this off, so it can be d.
You can reverse the order by adding a
“-r” to the history command.
The
“source -h” command reads the file in, but does not execute the commands.

You can automate this.
The
“savehist” variable specifies the number of lines to remember.
Therefore, when you type

set savehist = 10

and you log out, the program will save the last 10 lines in the file
“~/.history.” The next time the C shell starts up, it will read this file,
effectively executing the

source -h ~/.history

command. Large values of
will slow down the C shell during the start-up process.

The C shell numbers each command for reference.
Many people like to see these numbers automatically.
The C shell allows you to put this number into the prompt.
Placing the magic character
“!” in the prompt does this:

set prompt = ‘!% ‘

The command
“history” will display the list of past commands.
Add a number afterwards, and it limits the list to that number of commands.
Some people create aliases to make it easier to view the history:

alias h history

or

alias h “history 20”
alias H “history 100 | more”

The history mechanism isn’t just used to keep track of
your past commands. You can execute them again very easily.
The command

!!

executes the last command again.
Besides repeating the same command, it can be used
in other ways:

ls file?
# now rename each of these files
foreach i (`!!`)
mv $i $i.old
end

You can execute ANY command stored in the history list.
If you know the number in the history list
(or the number that was in the prompt), just specify the number.
Suppose the history command listed the following:

31 vi file1.c
32 make file1
33 ./file1

You could edit the file again with

!31

You can also specify the relative position, by putting a minus
before the number. The command
“!-2” executes the command before the last.
Remember, the position is relative.
So you can guess the relative position, and if you get the wrong
command,
type the same history command, and you will execute the next one in
the list.
In the vi/make/file1 example before, you can keep executing
“!-3” to execute the same three commands in a rotating order.

A third form uses the first few letters of the command.
To repeat the
command, you can use

!v

You only need to specify enough letters to match the desired command.
The first matching command, searching backwards, is executed.
This is my favorite method. It is not necessary to know the number, or
to list the history.

Suppose you typed the following commands:

make prog1;./prog1
make prog2;./prog2

If you type any of the following commands, you will execute the second
make command:

!m
!ma
!mak
!make

You cannot specify a pattern with a space. For instance, the command

!make prog1

do not execute the first
command.
To execute the first make command, without knowing the number,
you can tell the C shell to search for a string, and execute the
command that contains the string. This is done with the special
pattern
“?pattern?.” Therefore, to execute the first make command, type

!?prog1?

Often I find myself executing a command, and
wish to repeat the previous command, but append something to the end.
Just execute the
“!!” command, and append the addition to the end.
(This is why you cannot search for a command that contains a space).
I often develop complex filters on the fly. I type a command, and add
filters one step at a time. Here is an example, where I want to
find all lines that contain
“keyword” but not
“ignore.” Once I find this, I want the second word of the line, sorted.
One way to do this, without writing a shell script, is:

grep keyword file*
!! | grep -v ignore
!! | sort
!! | more

If you want to append to the last command, without adding a space,
you can. The following will print files
“prog” and
“prog1”

lpr prog
!!1
# same as
# lpr prog1

Suppose you want to append to a command that was not the last command?
This is no problem if you want a space between the old command and
the new word. If you edited file1.c, and wanted to edit that file and
a second file, you can type:

!v file2.c

This edits file1.c and file2.c
Now suppose you type the following commands:

vi File
chmod +x File
./File
cp File File1

and now you want to edit File1 without typing the complete line?
You can’t type

!v1

and

!v 1

will edit the wrong files.
There are two solutions. The first is to execute the
command again, and then append a
“1”

!v
!!1

There is another way. Remember that most UNIX shells have two ways to
specify a variable, $x and ${x}? The C shell history mechanism has a
similar feature. To append the number
“1” to the previous
command, type

!{v}1

This works for all of the examples discussed. That is, you can use the
curly braces to enclose the history specification:

!{-2}
!{32}
!{?File1?}

Adding the number
“1” without adding a space can be done by typing:

!{-2}1
!{32}1
!{?File1?}1

So far, I have only talked about using the history feature to
repeat entire command lines. You can also use it to repeat words.
The special variable
“!$” refers to the last word on the last line. This is very useful, if you
want to save keystrokes. Here is an example:

touch File
chmod +x !$
vi !$
./!$
cp !$ !$.orig

This is the same as typing

touch File
chmod +x File
vi File
./File
cp ./File ./File.orig

The variable
“!^” refers to the first argument on the line.
That is, instead of typing

touch File
cp File File.backup
vi File
chmod +x File
File abc

you could type

touch File
cp !^ !^.backup
vi !^
chmod +x !^
!$ abc

The string
“!!*” refers to all of the arguments on the previous line, except the first.
You can use this to reuse arguments:

ls *% %~ *.old *.backup
# A lot of files – move them into a directory
mv !* OldDirectory

In this case,
“!*” and
“!!*” mean the same.
There is another mechanism for specifying part
of the argument list.
A hyphen can specify a range. by itself, it’s the same as
the entire line, including the command.
Put a number afterwards, and it places a limit on the range:

ls f1 f2 f3 f4 f5 f6 f7 f8 f9
!!-4
# this is the same as
ls f1 f2 f3 f4 f5

I mention this for completeness.
Next month I will discuss more elaborate
variations. Notice that
“!-4” and
“!!-4” are
not the same.

I’ve mentioned that you can search for a command containing
a particular word. For instance, to repeat the command
containing
“ABC” type:

!?ABC?

It doesn’t matter where the string
“ABC” is on the line, the command will be executed again.
But sometimes you don’t want to execute the command again.
You just want to use the word.
As an example, suppose you execute

more A_file_with_a_long_name

Now suppose you type some other commands, and then decide to print
the file. You could type

!more
lpr !$

If you executed the
program a second time, this will not work.
You could type

history | grep A

and then repeat the command.
Or you could search for that line, and print the line out without
executing it, by typing

# print the command containing “A”
echo !?A?
lpr !$

But there is an easier way.
If you use the character
“%” after a search, it is the same as the entire word matched.
In other words, you can search for the line, extract the word,
and use it in one step:

lpr !?A?%
# same as
# lpr A_file_with_a_long_name

One of the most useful features of the C shell is the ability
to correct a mistake. If you make the following typo:

mroe File

and you want to change
“mroe” to
“more,” you can simply type:

^ro^or^

The shell changes
“ro” to
“or,” and repeats the commands.

Someone onced asked me if there was a way to do this with a function
key.
They kept pressing the backquote by mistake.
That is, they typed

ls`

and wanted an easy way to fix this.
If this was done in a
window, there is a solution.
Place the following in your
file:

# i.e. csh history
mapi F7 ^`^n

This maps the F7 function key to effectively type

^`^

and type return at the same time.
You can also use this to duplicate other common operations.
Alas – this only works with
and not in
mode.

One more thing, recent versions of Solaris do not require you to type
the second up-arrow. If you want to delete the letter
“x” from the previous command, just type

^x

and the letter will be deleted.

Last month I discussed the history mechanism.
I showed how you could use it to execute commands without typing the
entire command again, by using the
“!” character.. I also discussed the substitution mechanism,
triggered by using the
“^” character.
Different characters can be used, by modifying the value of the
histchars variable, which has the default value of
“!^.”

There are three types of history substitutions:
events, words, and word modifiers.
I discussed event designators last month.
These correspond to lines typed at the keyboard.
A summary of event designators follows:

+-----------------------------------------------------------+
|Format	  Example   Meaning				    |
+-----------------------------------------------------------+
|n	  !2	    Command from line #2		    |
|-n	  !-3	    Command 3 commands ago		    |
|#	  !#	    The current command			    |
|!	  !!	    The last command			    |
|s	  !abc	    The last command that starts with 'abc' |
|?s?	  !?abc?    The last command that contained 'abc'   |
+-----------------------------------------------------------+

I didn’t mention the
“!#” event last time. This is a feature of newer versions of the
C shell.
It matches the current line. It isn’t much used unless you use some of
the features described below.

long_word !#

is the same as

long_word long_word

Yeah.
That’s real useful.

The previous events refer to complete lines.
You don’t have to recall previous lines, and use the entire line.
You can just use part of the line. Last month I discussed four
word designators.
If the last command was

program arg1 special2 arg3 arg4

Then the value of these word designators would be

+-----------------------------------------------+
      |Character   Example    Value		      |
      +-----------------------------------------------+
      |^	   !^	      arg1		      |
      |*	   !*	      arg1 special2 arg3 arg4 |
      |$	   !$	      arg4		      |
      |%	   !?spec?%   special2		      |
      +-----------------------------------------------+

These word designators are specialized abbreviations of
a more flexible, but complex syntax.
All five examples below are identical:

program arg1 arg2
# now print arg2
lpr !$
lpr !!$
lpr !!:$
lpr !{!:$}
lpr !:$

These word designators are specialized abbreviations of a more flexible, but complex syntax. All five examples below are identical:

Using the last syntax, it is possible to specify any word on the previous
command line, besides the first or last. Just specify the number:

lpr !:2

It is important to remember that the history mechanism comes early,
before the meta-characters are expanded.
For instance, suppose the following command was typed:

program abc{1,2,3} *.? “a b”;program2>file.out

This table lists the words that can be recalled in a history event:

+------------------+
		    |Word   Value      |
		    +------------------+
		    |!:0    program    |
		    |!:1    abc{1,2,3} |
		    |!:2    *.?	       |
		    |!:3    "a b"      |
		    |!:4    ;	       |
		    |!:5    program2   |
		    |!:6    >       |
		    |!:7    file.out   |
		    +------------------+

Notice how the shell separates words not based on white-spaces, but on
meta-characters like
“>” and
“;.”

Notice how the shell separates words not based on white-spaces, but on meta-characters like “>” and “;.”

I’ve already mentioned that
“!!:5” is the same as
“!:5” when used to refer to the fifth word of the previous line.
Two different syntaxes exist, because you can use these word modifiers
to refer to any command stored in the history memory.
If the history contained the following command:

cc -o prog prog.c
./prog >A_long_file_name

then the following table shows some of the values

+-----------------------------+
	       |Modifier    Value	     |
	       +-----------------------------+
	       |!c:2	    prog	     |
	       |!?long?:2   A_long_file_name |
	       +-----------------------------+

You can specify range of words, using the
“-” modifier.
Assuming the command

program a b c d e f g h

then the following table shows possible ranges of words:

+---------------------------+
		|Variable   Value	    |
		+---------------------------+
		|!!:2	    b		    |
		|!!:4	    d		    |
		|!!:2-4	    b c d	    |
		|!!:2-	    b c d e f g	    |
		|!!:2-$	    b c d e f g h   |
		|!!:2*	    b c d e f g h   |
		|!!:-	    a b c d e f g   |
		|!!:1-$	    a b c d e f g h |
		|!!:*	    a b c d e f g h |
		+---------------------------+

As you can see, if the value before the hyphen is omitted,
then the default beginning is 1.
If the value after the hyphen is omitted, the defaults is the next to
last argument.
In other words,
“*” acts like
“-$” when used after a number.
I should also mention that the rules for abbreviations are confusing.
“!!:-” is the same as
“!:-” but it is not the same as
“!-” because the last looks like the relative event identifier, i.e.
“!-2.”

As you can see, if the value before the hyphen is omitted, then the default beginning is 1. If the value after the hyphen is omitted, the defaults is the next to last argument. In other words, “*” acts like “-$” when used after a number. I should also mention that the rules for abbreviations are confusing. “!!:-” is the same as “!:-” but it is not the same as “!-” because the last looks like the relative event identifier, i.e. “!-2.”

I haven’t discussed aliases in detail, but the mechanism used for
history are also used in defining aliases.
For instance, to make an alias so that

compile xyz

does the same as

cc -o xyz xvz.c

you would use the alias

alias compile ‘cc -o !:1 !:1.c’

Find this confusing? Wait till you learn about variable modifiers.

The C shell has variable modifiers, that can be used
to extract part of a variable.
That is, if a variable
“x” has the value
“file.c,” and if you wanted to remove the
“.c” part, then you can use the
“root” modifier
“:r.” That is,
“$x:r” is the same as
“file.” There exists four useful modifiers, that extract the head, tail, root
and extension of a variable.
Assume a variable has been set by typing:

set a = “/a/b/c/d.e.f.g”

Then the four modifiers would give the following results:

+-------------------------------------------------------+
  |Modifier   Meaning		    Example   Results	  |
  +-------------------------------------------------------+
  |r	      Root		    $a:r      a/b/c.d.e.f |
  |e	      Extension		    $a:e      g		  |
  |h	      Head (or Directory)   $a:h      /a/b	  |
  |t	      Tail (or Filename)    $a:t      c.d.e.f.g	  |
  +-------------------------------------------------------+

One way to think of this is to realize that
Root and Extension are matching pairs. That is,
“${a:r}.${a:e}” is the same as
“$a.” Head and Tail, or rather, Directory and Filename are also matching.
“${a:h}/${a:t}” is the same as
“$a.”

One way to think of this is to realize that Root and Extension are matching pairs. That is, “${a:r}.${a:e}” is the same as “$a.” Head and Tail, or rather, Directory and Filename are also matching. “${a:h}/${a:t}” is the same as “$a.”

Earlier, I mentioned how the syntax of the C shell can be complex.
These variable modifiers can be used for variables, arguments,
history
and aliases.
Let me give some examples.
If you wanted to rename all files with the extension
“.old” to the extension
“.new,” then use

foreach i ( *.old )
mv $i $i:r.new
end

To make a shell script called
“compile” that did the same as the alias above (except the .c is not needed), use

#!/bin/csh -f
cc -o $1:r $i:r.c

An alias to do the same would be

alias compile ‘cc -o !:1:r !:1:r.c’

Lastly, suppose you wanted to execute the following:

diff file.old file

There are several ways to do this.
You can use the in-line expansion:

diff file{.old,}

You can also use the
“!#” value, combined with a way to get one word from the event, with a
variable modifier:

diff file.old !#:$:r

Of course that example is a bad one for several reasons.
The abbreviation is
longer than typing
“file.” Also – it doesn’t work. I tried it, got a segmentation fault, the
shell exited, and my window disappeared. It’s so much fun researching
these little-used features. Using
“!#:1:r” worked, however. Go figure.

There are other modifiers.
You can use
“:p” as a
“print, but not execute” modifier.
If you wanted to see the command that started with
“abc” but did not want to execute it, you could type:

echo !abc

The
“:p” modifiers does this, with fewer characters. Just type

!abc:p

and the history value is printed, but not executed.
This modifier isn’t useful for the other cases.
If you can find a use for variables, arguments or aliases, let me know.

A useful modifier is
“:s,” as it can be used to perform simple substitutions
on all variables.
If you wanted to change
“old” to
“new” in a filename, use

#!/bin/csh -f
mv $1 $1:s/old/new/

An alias would be

alias old2new ‘mv !:1 !:1:s/old/new/’

This substitution always changes the first string found.
Any character can follow the
“s” character; it is used as the delimiter.
Note that
“!!:s^” is the same as
“^” when the later is used at the beginning of a line.

The string substituted is not a regular expression.
The characters are ordinary. There is one special character, when used
in the second pattern –
“&.” This matches the string in the first part.
Suppose you typed

echo abc.{1,2}

(which prints abc.1 abc.2)
and you wanted to change this to

echo {abc,def}.{1,2}

(which prints abc.1 abc.2 def.1 def.2),
you can use the
“&” character like this:

^abc^{&,def}

Suppose you type the following command:

cc -o trial trial.c

and you want to change
“trial” to
“program.” If you type

!!:s^trial^program^

or more simply

^trial^program

then the first change will be made.
This will be the same as typing

cc -o program trial.c

This doesn’t change the second occurrance.
If you want to repeat it, then either type the same command a second
time, or use the
“:&” modifier, which says to repeat the last substitution.
If you add a
“g” before the
“&” then the substitution is repeated on each word.
Instead of typing

program abc.1 abc.2 abc.3 abc.4
program def.1 def.2 def.3 def.4

You could type

program abc.1 abc.2 abc.3 abc.4
# Now change ‘abc’ to ‘def’, but don’t execute it
^abc^def^:p
# Now repeat it for each argument
!!:g&

The last step will echo
“program def.1 def.2 def.3 def.4” and then execute it.
This only changes the first occurrence in each word.
Suppose the following lines were executed:

echo a aa aaa aaaa
^a^A^:p
!!:g&

This last line is equivalent to executing

echo A Aa Aaa Aaaa

The tcsh variation has a
“a” modifier in addition to the
“g” modifier. If present, then the change is made several times in each word.
If your shell has this, you could change all lower case
“a’s” to upper case
“A’s.”

The C shell and Bourne shell behave differently when
a filename pattern is used, and nothing matches.
Suppose you have a shell script, named
“test_me,” that says

# The test_me script, either sh or csh
echo $1

and you call it using:

test_me ?

The Bourne shell will echo
“?” which the C shell will report
“echo: No match.” You can disable this error by setting the
nonomatch variable:

#!/bin/csh -f
set nonomatch
echo $1

The other way to do this is to use the
“:q” modifier, which quotes the variable:

#!/bin/csh -f
echo $1:q

Suppose you had a script that was called with the following argument:

test_1 ‘This is a question?’

This script has one argument. If you wanted to pass it to a second
script,
and wanted to retain the meta-characters like
“?” and
“*,” simply use the
“:q” modifier described above:

#!/bin/csh -f
# This is the test_1 script
test_2 $1:q
# or use
set nonomatch
test_2 “$1”

The second script will get the identical argument the first one has.
But what would you do if you wanted to separate the words into
arguments, but leave the question mark alone?
You could use the
nonomatch variable:

#!/bin/csh -f
# This is the test_1 script
set nonomatch
test_2 $1

Another choice is to use the
“:x” modifier, which is like the
“:q” modifier, but separates words when whitespace is found:

#!/bin/csh -f
test_2 $1:x

The tcsh variable supports two additional modifiers.
“:u” makes the first lowercase letter uppercase, and
“:l” makes the first uppercase letter lowercase.

There are a few more points to mention. You can have multiple
variable modifiers on a single variable.
In some cases, braces are needed to specify the variable part.
In complex cases, the tcsh variant of the C shell behaves differently.

Well, that is everything I know about the history feature of the C
shell. It is confusing, but I tried to come up with examples of all of
the main features. I hope you found this interesting.

I’m lazy.

If there is something that I do on the computer a lot, I look for ways
to make my life easier. If there is something that takes ten seconds to
type, I’ll do whatever it takes to save nine seconds of those ten, even if it
takes me days to accomplish this. Weeks, even. Months. Years. No. Not
quite. I’m not
compulsive, you know. Don’t be silly.

C shell users have a very important tool to save those extraneous
seconds: aliases. There are several alternative techniques to save
keystrokes. In the last two columns I discussed the history function in
detail. You can also create shell scripts. However, shell scripts
run in a new shell process. You cannot use them to change your current
shell process. Most of you have tried this, by creating a script that
says something like:

#!/bin/csh -f
cd newdirectory
setenv VAR `pwd`

If you execute this script below, will the directory be changed?

myscript;pwd;echo $VAR

The answer is no. The current shell executes a new shell, which
changes its directory. However, this shell, being a child, does not
affect the parent shell.
Another technique is needed.

The third method is to use variables as commands. Many people forget
about this particular approach. The following commands will execute
the contents of the C shell script in the current shell, changing the
current directory:

set DO = “source ~/bin/myscript”
$DO

The fourth way is to use aliases, which is the subject of this month’s
tutorial.

alias DO “source ~/bin/myscript”
DO

There are several advantages to aliases.

·
You can save keystrokes.
·
Simple aliases are easy to understand.
·
Changes affect the current shell.
·
Meta-characters can be passed without quoting.

But there are several disadvantages:

·
Complex aliases have a confusing syntax.
·
Certain characters must be quoted to pass them into an alias.
This makes the syntax
more complex.
·
Aliases are defined on a single line.
This makes it difficult to document complex aliases,
and multiple-lined aliases must have the newline quoted.
·
Because the C shell syntax requires certain words on the beginning of
the line, it is difficult to include commands like
while, or
foreach in the alias definition.
Using these in aliases require additional quoting, adding more complexity.

Bourne shell functions were added long after C shells
had the alias. They act like aliases, but do not suffer from the above
problems. Instead, Bourne shell functions have the following
advantages:

·
Bourne shell functions have the same syntax as shell scripts.
·
Bourne shell functions can be easily documented, especially those that
are several lines long.
·
Bourne shell functions don’t require additional quoting, and the
quoting is more consistant.

All-in-all, the concept of C shell aliases is flawed. They are fine
for simple definitions, but if you need anything more complex,
I suggest you use a shell script (in whatever shell you prefer)
or define an alias to source the script, as I did above.

I have the following in my
file:

if ( -f ~/.aliases && -o ~/.aliases ) source ~/.aliases

This sources my alias file if the file exists and I own it.
This isn’t high security, but I no longer wake up screaming in the
middle of the night.
You can make sure that you only read this file once, by using a
special variable:

if ( ! $?ALIAS_def ) then
if ( -f ~/.aliases && -o ~/.aliases ) source ~/.aliases
endif

Inside the file
you need to add the line:

set ALIAS_def

Some people include the following aliases:

alias rm rm -i
alias mv mv -i
alias cp cp -i

This is a good idea. But remember that if you change to
another user ID, (like the superuser), these aliases may not be
there. So don’t assume they always exist.

Aliases can also abbreviate commands:

alias a alias
# create aliases for “more” and “emacs”
a m more
a e emacs

There are variations of the
command, that I’ve seen many people define as aliases:

alias lf ls -F
alias la ls -a
alias li ls -i
alias ll ls -l
# yada yada…

These alias, composed of a single command and options,
allow arguments:

lf A*
ll *.c

There are two ways to disable an alias.
The first is to remove the definition:

unalias rm mv cp

If you want to ignore an alias once, then quote it. That is, make part
of the command quoted. This by-passes the alias expansion. Examples:

rm file*
“mv” file1 file2
“”cp new old

Aliases can refer to other aliases:

alias ll ls -l
alias llF ll -F

The second alias uses the first alias. Be careful of alias loops:

alias AA BB
alias BB AA

If you execute either command, the C shell will report
“Alias loop.”

Aliases can be several commands, piped together:

# do an ls -l, but only list directories
alias ldir ‘ls -l|grep “^d”‘

I often use the aliases below. They sort
various files, based on size, date, or accessed date:

# sort by date:
alias newest ‘ls -lt | head -30’
alias oldest ‘ls -ltr | head -30’
# sort by size:
alias biggest ‘ls -ls|sort -nr | head -30’
alias smallest ‘ls -ls|sort -n | head -30’
# sort by time last used
alias popular ‘ls -lut | head -30’
alias unpopular ‘ls -lutr | head -30’
# Sort by link time
alias lsst ‘ls -lct | head -30’
alias lsstr ‘ls -lctr | head -30’

Click here to get file: Aliases4.csh
These last few aliases, however, do not take arguments in the proper
place. Typing

biggest [A-Z]*

is the same as

ls -lut | head -30 [A-Z]*

This isn’t what a user might expect.

It is possible to pass arguments to aliases.
The syntax for aliases is based on the same crufty syntax for the history
mechanism. The string
“!*” matches all arguments. The exclamation mark must be quoted by a
backslash:

# sort by date:
alias newest ‘ls -lt !* | head -30’
alias oldest ‘ls -ltr !* | head -30’

Some aliases will only work with a single argument. That is, if you
give it two arguments, the program will complain with an error
message.
Let’s assume you want an alias to recursively search for a file.
That is, the alias will search from the current directory, and go
inside any subdirectories. The only argument is a pattern that
describes the filename:

% findfile test*
-rw-r–r– 1 barnett staff 22027 Nov 9 23:32 ./test.pl
-rw-rw-r– 1 barnett staff 18520 Aug 26 12:13 ./Old/test.out
-rwxrwxr-x 1 barnett staff 18557 Sep 12 09:43 ./Tmp/test.sort

Notice the asterisk is
not quoted.
If this was a shell script, you would have to quote the
meta-character like this:

findfile test*
or
findfile ‘test*’

The C shell alias doesn’t need to have meta-characters quoted,
because the alias
substitution happens
before the meta-character for filenames are expanded.

You can reuse a single argument. Here is an alias I use when I want to
work on a copy of a file, and leave the original alone, keeping the
date the same:

alias orig “mv !:1 !:1.orig;cp !:1.orig !:1”

typing
“orig file.c” does the following:

mv file.c file.c.orig
cp file.c.orig file.c

I use this alias, because it keeps the original version of the file
unchanged. If I ever examine the dates of the new and old file, the
original file has the original date. If I just executed
“cp file.c file.c.orig” and then edited
“file.c” the dates of the two files would be close to identical.

Compiling C programs can be complex, especially if you do not have a
to go with it.
Here are some that can be used to compile C programs:

alias ccc ‘cc -o !:1:r !*’
alias ccg ‘cc -g -o !:1:r !*’
alias cco ‘cc -fast -o !:1:r !*’
alias ccx ‘cc -o !:1:r !* -L${OPENWINHOME}/lib -lX11

Use them as following

ccg main.c part1.c part2.c

This compiles programs without needed a
. Here is one that is useful to kill a process:

alias slay ‘set j=`/usr/ucb/ps -ax| grep !*|head -1`;
kill -9 `echo $j[1]`’

Notice how it uses a C shell array to extract the first word on the
line (i.e. the PID or the Process Identification Number).

You can pick and choose the arguments you want.
If you wanted an alias to move to a directory, with the directory as
the first argument, use

# as in
# moveto directory *.c
alias moveto ‘mv !:2* !:1’

Some examples of arguments inside an alias follow:

+----------------------------------+
	    |	     Aliases arguments	       |
	    +----------------------------------+
	    |Variable	meaning		       |
	    +----------------------------------+
	    |!:1	Argument 1	       |
	    |!:2	Argument 2	       |
	    |!*		Arguments 1 through n  |
	    |!:1-$	Arguments 1 through n  |
	    |!:1*	Arguments 1 through n  |
	    |!$		Nth argument	       |
	    |!:-	Argument 1 through n-1 |
	    |!:2-	Argument 2 through n-1 |
	    |!:2-$	Argument 2 through n   |
	    |!:2*	Argument 2 through n   |
	    |!:2-4	Arguments 2, 3 and 4   |
	    +----------------------------------+

You can redefine any command with an alias:

alias cat mycat
alias /bin/cat mycat
alias /usr/bin/cat mycat

You can also
“trap” commands, and execute a special command:

alias command ‘/source ~/.command; /bin/command’

You can create an alias that spans over several lines.
Here is one that compiles a C program. If you tell it to compile a
program that does not end with a
“.c,” an error occurs. That is, if you type:

C file1.f

The message is this:

Error: this is for C programs only
Extension should be .c on file file1.f, not .f

On the other hand, if you typed

C prog.c file1.c file2.c file3.c

and the file
“prog” existed, the alias would do the following:

mv prog prog.old
cc -o prog proc.c file1.c file2.c

Here is the alias:

alias C ‘eval “if (!:1 !~ *.c) then
echo “Error: this is for C programs only”
echo “Extension should be .c on file !:1, not .!:1:e”
else
if ( -e !:1:r ) mv !:1:r !:1:r.old
cc -o !:1:r !:1:r.c !:2*
endif

Click here to get file: AliasesC.csh
Notice how the alias includes an
“eval” call. This makes sure the meta-characters are expanded.
They are quoted in the alias, so they are unchanged so the alias can
be defined. The
“eval” command reverses this action. Also note the liberal use of the
“:r” variable modifier.

I have tried to use aliases that use
foreach and
while commands.
To be honest, I find them impossible to write. I suggest you use a
shell script if possible. There are, however, times when a shell script doesn’t
work well.
Suppose you want to source several files.
You could type

foreach i ( *.alias )
source $i
end

This, however, could
not be done with a shell script.
You can try it, but your current shell would not know about the
aliases, because a different shell is executing the commands.
Below is an alias that will solve the problem, however.
It has the advantages of an alias, without the
disadvantages of trying to get the C shell to work on one line.
The alias is

alias FOREACH ‘set a = !:1;
set b = (!:2*);
source ~/source_alias/FOREACH.csh;’

Really, this alias is in two parts. This first part sets two
variables, and sources a file, the second part. I have created a
special directory that contains these sourced aliases.
This allows me to source them in easily, and to keep them in one
location.
The file looks
like this:

#!/bin/echo use source to execute this command
# variable a = filename metacharacter
# variable b = command to execute
foreach i ( $a )
eval $b $a
end

To use this, type

FOREACH *.csh source

Note how the first line starts with a
“#!/bin/echo” command. This is to make sure that people source the file, and not
execute it.

Now, for a special treat, (I’m proud of this next trick) I have a more
powerful version. Suppose we wanted to take each file, and rename it
with a
“.old” extension. That is, suppose you type:

FOREACH *.csh mv # #.old

The character
“#” is used as a special character, and it changes to match each argument
in the list.
This does the same as typing the following, but one line is used.

foreach i ( *.csh )
mv $i $i.old
end

Since this is starting to get a bit complex, I combined the definition
of the alias with the script itself. You source this file to define
the alias. You also source the same file to execute the script.
Therefore both parts are in the same file:

#!/bin/echo use source to execute this command
# variable a = filename metacharacter
# variable b = command to execute

# source this to define the alias
if ( ! $?FOREACH_def) then
alias FOREACH ‘set a = !:1;
set b = (!:2*);
source ~/source_alias/FOREACH.csh;’
set FOREACH_def
else
echo $b | grep ‘#’ >/dev/null
# remember status
set r = $status
foreach i ( $a )
if ( $r == 0 ) then
# change ‘#’ to $i
set B = `echo $b | sed ‘s/#/’$i’/g’`
else
# Add a ‘$i’ to the end, if it is missing
set B = `echo $b | sed ‘s/$/ ‘$i’/’`
endif
eval $B
end
endif

Click here to get file: Foreach1.csh
This script is upwardly compatable with the previous script.
If you typed

FOREACH *.csh source #

this does the same as typing

FOREACH *.csh source

In other words, if you omit the
“#” it assumes there is one at the end.
However, this script does not remove the extension. If I wanted a
script
that converted all files ending in .c to files ending in .old.c, I
could not use the above script. Here is another one, slightly
different, called
“FOREACHr,” that removes the extension from the arguments. I added a
“r” on the end to remine me that it uses the
“:r” variable modifier.
To use it, type

FOREACHr *.c mv #.c #.old.c

The script is almost identical to the previous:

#!/bin/echo use source to execute this command
# variable a = filename metacharacter
# variable b = command to execute

# source this to define the alias
if ( ! $?FOREACHr_def) then
alias FOREACHr ‘set a = !:1;
set b = (!:2*);
source ~/source_alias/FOREACHr.csh;’
set FOREACHr_def
else
echo $b | grep ‘#’ >/dev/null
# remember status
set r = $status
foreach i ( $a )
# Here is the different part
set j = $i:r
if ( $r == 0 ) then
# change ‘#’ to $j
set B = `echo $b | sed ‘s/#/’$j’/g’`
else
set B = `echo $b | sed ‘s/$/ ‘$j’/’`
endif
eval $B
end
endif

Click here to get file: Foreach2.csh
I hope you enjoyed my examples. I tried to illustrate the important
points, and give useful examples. Next month, I’ll tackle directories
and prompts.

This section talks about the
“cd” command.
Wait! Come back. Sure, everyone knows this command.
It’s the first command UNIX users learn.
Sounds like an excellent reason to discuss it.
Ah, you question my sanity. It’s okay. I’m used to it.
It’s a good topic, because it has subtle abilities and most people
are ignorant of them.

Directories and paths are either absolute (starting with
“/)” or relative (starting with any other character).
The directories
“.” and
“..” are special. The first specifies the current directory, and the second
the parent of the current directory.
The command

cd ./dir/../dir/../.

will not change the current directory.

If you get lost, or you simply want a quick way to go back to your
home directory, the command

cd

with no arguments takes you to your login directory.

Normally, when you start up your window system, each new window starts
up with the working directory being the same as the one you were in
when you started up the windowing system.
However,
“cd” with no arguments still takes you to your home directory.
Alternately, you can change your home directory:

set home = /usr/project

then every time you type
“cd” or
“cd ~” you will go to the projects directory instead of your normal home directory.
The variable
“home” is special because it is automaticallt converted to the
“HOME” directory, and exported.
The character
“~” is an
abbreviation of the variable
“$home.”

Your true home directory, or any user’s home directory, which is
determined by the entries in the
“/etc/passwd” file, can be
accessed by

cd ~username

even if you change the variable
“home.”

You may occasionally type the
“cd” command and get the error
“no such file of directory.” Perhaps you forgot which directory you were in, or forgot to add
“~/” or
“../” before the name.
This can be fixed. If you have a set of favorite directory where you
normally create new directories, you can specify this set, by setting
the variable
“cdpath.” This variable accepts a wordlist. Example:

set cdpath = ( .. ~/Src /usr/projects ~ )

Now when you type

cd prog

the system will look for

./prog
../prog
~/Src/prog
/usr/projects/prog
~/prog

in that order.

Another way to access favorite directories is to define variables with
the names of the directories. Example:

set Src = “~/Src”
set p = “/usr/projects”

You can now use the commands

cd $Src
cd $Src/program
cp $P/data .

The command
“cd” will test for one more conditions
before reporting an error. It will look for a variable with the same
name as its argument.
Therefore the two commands below are equivalent:

cd $P
cd P

Remember that the C shell first looks for the directory in the current
directory, then the list in
“cdpath,” and finally the variable.

This can be used by adding the following alias to your .cshrc file:

alias = ‘set !:1=$cwd’

Then you can type

= A

This remembers the directory.
Whenever you type

cd A

you go to that directory. You can also go to another directory, and
refer to the old directory:

= A
cd NewDirectory
cp $A/file .

Remember that only
“cd” will test for a variable. So commands like

cp A/file .

won’t work.

You can also use aliases. Executing the command

alias projects ‘cd /usr/projects’

will define a shortcut to specify a change in a directory.

There are two ways to find out what your current working directory is.
The first is with the program
“pwd” – print working directory.
The second is with the variable
“cwd,” which can be examained by

echo $cwd

or by creating a new alias

alias cwd ‘echo $cwd’

Examining the internal variable
“cwd” is faster than executing the
stand-alone program
“pwd,” but there is one subtle difference.
If you access a symbolic link in your directory path, then
“pwd” will
show the actual directory path, while
“cwd” will show the path you
used to get to the directory. For instance, the command

cd /usr/tmp; pwd; echo $cwd

might output the following:

/var/tmp
/usr/tmp

The first is the actual directory, while the second is the directory
you
think you are in.
You can force directories to be displayed with the true path by the
C-shell command

set hardpaths

NOTE: what about cd /usr/tmp/..?

The C-shell also provides a convenient method of changing between a
common set of directories. It keeps a
“directory stack” – which can be
displayed with the command

dirs

There is an optional
“-l” argument which expands the
“~” abbreviations.

You can make use of this stack by using the command
“pushd” – push
directory – instead of
“cd.” They both change directories, but
“pushd” adds your old directory to the stack, and puts the new directory on
the top of the same stack.

Here is an example (lines starting with
“%” are typed by the user)

% dirs
~
% pushd /usr; dirs; pwd
/usr ~
/usr

To return to the old directory, (i.e. the second director on the
stack), use the command

popd

If you merely wish to exchange the first and second directory, the
command
“pushd” with no arguments will do this. If you repeat this,
you go back again.
“Pushd” is very convenient when you wish to go back
and forth between two directories.

“Cd” only changes the top directory. If, therefore, you are in a
projects directory, but are interrupted, you can
“pushd” to the new
directory, and
“cd” to several other directories. When you are done,
“popd” will return you to the directory before the interruption.

Both
“pushd” and
“popd” can have an argument consisting of the
character
“+” followed by a number.
“popd” will discard the
“nth” entry in the stack, without changing the current directory.
“pushd” will change the current directory to the
“nth” entry, rotating the
entire stack so that entry is now on top.

For instance, if you had the stack

/usr/spool/news/comp/sys /usr/spool/news/comp /usr/spool/news /usr/spool /usr

the command

pushd +2

will change the stack to

/usr/spool/news /usr/spool /usr /usr/spool/news/comp/sys /usr/spool/news/comp

bringing entry 2 to the top, entry 3 to be second from the top, etc.
The top of the stack is entry 0.

Some people like to keep their current stack of directories in an
array.
This is simple:

alias pushd ‘pushd !* && set dirs = (`dirs`)’
alias popd ‘popd !* && set dirs = (`dirs`)’

This allows you to use
“$dirs[2]” in command lines, and to search for files:

cp $dirs[2]/file $dirs[3]
foreach dir ( $dirs )
if ( -f $ddir/DATA ) echo $dir/DATA found
end

You can clear the stack by typing

repeat 9 popd

Others like to create aliases:

alias +1 pushd +1
alias +2 pushd +2
alias +3 pushd +3
alias -1 popd +1
alias -2 popd +2
alias -3 popd +3

Be aware that
“cd” is built into the shell. The command
“chdir” is a
synonym, convenient when creating aliases for
“cd.” So executing cd
in a shell script will not change your current shell’s directory. If
you want to do some clever things, like changing your prompt to
reflect your current directory, you have to use the alias feature. But
when the alias is combined with the
“source” command in the C-shell, a
lot of flexibility is available.
But more on that later.

This alias will echo your current directory whenever you change it.

alias cd ‘cd !*;echo $cwd’

However, you must be careful of alias loops.
As a general rule, I use
“chdir” instead of
“cd” in aliases, to prevent a potential loop. Therefore the above should
be:

alias cd ‘chdir !*;echo $cwd’

Suppose you want to execute a special command whenever you change
directories. Or you want to change your aliases whenever you change
directories. The following example will execute the commands in the
file
“.dir” whenever you change directories and it finds the file
“.dir” in the directory and you also own it.

alias cd ‘chdir !*; if ( -f .dir && -o .dir ) source .dir ‘

The test for ownership,
“-o,” protects you from executing someone
else’s copy of
“.dir.” You could instead use two files, say called
“.in” and
“.out” and execute one when you eeenter a directory, and another when you leave.
Both choices are dangerous, because someone might have write access to
one of your files, and trick you into executing a command.

These aliases allow you to move up and down directories, and the
command
“.” is easier to type, and faster, than
“pwd.”

alias . ‘echo $cwd’
alias .. ‘set dot=$cwd;cd ..’
alias , ‘cd $dot ‘

Some people simply use the alias

alias cwd echo $cwd

Many people like to have their prompt change to show the current
directory. Others like to display the history number.
All of these can be done.
The character
“!” has a special meaning when the
“prompt” variable contains it. It is expanded to be the current command number.
You don’t need to type the
“history” command to learn the number of a previous command.
Just type

set prompt=”! % “

Or create an alias

alias SP ‘set prompt=”! % “‘
SP

Others like to show the current directory in the prompt.
This can be combined with the cd alias above:

alias cd ‘chdir !*;SP’
alias SP ‘set prompt=”! $cwd % “‘

Finally, here is a elaborate example that displays

command number
hostname
user
current directory

with each prompt with the format of “10 hostname {username} cwd >”

alias cd ‘chdir !*;SP’
alias SP ‘set prompt=”! `hostname` {$USER} $cwd > “‘

If you would rather have just the base directory (the last directory in the path)
instead of the entire path,
try:

alias SP ‘set prompt=”! `hostname` {$USER} `basename $cwd` > “‘

or

alias SP ‘set prompt=”! `hostname` {$USER} $cwd:t > “‘

instead of the above line.

Some people even use multi-line prompts:

set hostname = `hostname`
alias SP ‘set prompt=”
${hostname}::${cwd}
! % “‘

Next month, I will explain my system for integrating
diretory management with the window system.
I have used more elaborate aliases that execute programs which provide
directory selection from the current stack using cursor keys.
But that is beyond this tutorial. Instead, I would like to end with a
popular set of aliases that changes the black bar on top of each
SunView window to show the current hostname and directory stack.
In addition, it adds the following commands:

+---------------------------------------+
	  |Command   Function			  |
	  | _					  |
	  | +	     alias for "pushd"		  |
	  | -	     alias for "popd"		  |
	  | ~	     alias for "cd ~"		  |
	  | .	     update top stripe, show jobs |
	  | ..	     go up one directory	  |
	  | ,	     go back down (used with ..)  |
	  | --	     go to last directory	  |
	  +---------------------------------------+

This was documented in the SunOS Release 3.5 manual, but that version had
some errors. The characters
“^[” below must be changed to an escape character.

This was documented in the SunOS Release 3.5 manual, but that version had some errors. The characters “^[” below must be changed to an escape character.

#!/bin/sh
# Zappath: created by Bruce Barnett
# this script edits the output of the C shell “dirs”
# command and shortens the strings to a compact form
#
# Some example editing:
#
# remove the automount /tmp_mnt prefix
# change /usr/export/home to /home
# change /homedisk to /home
# change $HOME into ~
# change /home/abc to abc
# change /usr/etc to ./etc
# change */*/ABC to ./ABC
# one more thing:
# must change ~ to be –
sed ‘
s:/tmp_mnt::g
s:/usr/export/home:/home:g
s:/homedisk:/home:g
s:’${HOME}’:~:g
s:/home/::g
s:/usr/:./:g
s:[^/ ]*/[^/ ]*/:./:g
s:~:-:g

Click here to get file: Zappath.sh

# C shell aliases to display hosts, directories, and directory stacks
# in the window title bar, icon string, and directory prompt
# created by Bruce Barnett
# Based on the SunOS 3.5 Release notes
# Usage:
# if ( -f ~/.header && -f ~/bin/Zappath ) source ~/.header
#
# the SP alias sets the directory prompt
# the setbar alias changes the window title bar and icon string
# define them here as the default case

alias SP ‘set prompt=”$cwd:t% “‘
alias setbar ‘echo !* >/dev/null’

# If not a sun cmdtool or shelltool, or not an X terminal, exit.
if ( ! ( $term =~ sun* ) && ! ( $term =~ xterm )) goto getout

# if using a raw console, don’t do anything
if ( `tty` =~ /dev/console ) goto getout

# set a few variables for later
# but only if the environment variable is not set

if ( ! $?HOSTNAME ) then
setenv HOSTNAME `hostname`
endif

# find the home machine
# is there a file that has a machine name in it?
if ( -f ~/.display ) then
set mymachine = `sed -e ‘s/:.*//’
else
# obviously change this to match your
# default system. Mine is “grymoire” – of course
set mymachine = “grymoire”
# alternately, some people use “who am i”
endif

set console = ‘<< CONSOLE >>’

# figure how how to generate escape, bell,
# and echo commands without a a line terminator
# I may have done this before. If so, the variable E is set

# have I executed this script before on this system?
if ( $?E ) then
# echo “already set the echo variables”>/dev/tty
else if ( -f ~/.echo.${HOSTNAME} ) then
source ~/.echo.${HOSTNAME}
else if ( `echo -n |wc -l` == 0 ) then
# echo “built in echo is bsd” >/dev/tty
# then berkeley style echo
echo ‘set ech = “echo -n”‘ >~/.echo.${HOSTNAME}
echo “set E = `echo a | tr a ‘ 33’`” >> ~/.echo.${HOSTNAME}
echo “set B = `echo a | tr a ‘ 07’`” >> ~/.echo.${HOSTNAME}
echo ‘set N = “”‘ >> ~/.echo.${HOSTNAME}
source ~/.echo.${HOSTNAME}
else
# echo “built in echo is sysV” >/dev/tty
echo ‘set ech = “echo”‘ >~/.echo.${HOSTNAME}
echo ‘set E = ” 33″‘ >> ~/.echo.${HOSTNAME}
echo ‘set B = ” 07″‘ >> ~/.echo.${HOSTNAME}
echo ‘set N = “”‘ >> ~/.echo.${HOSTNAME}
source ~/.echo.${HOSTNAME}
endif

# Are we using shelltool, cmdtool or xterm?
# duplicate these aliases here to avoid problems
if ( $term =~ sun* ) then
# Sun Aliases
alias Header ‘${ech} “${E}]l!:1${E}${N}”‘
alias IHeader ‘${ech} “${E}]L!:1${E}${N}”‘
else if ( $term =~ xterm ) then
alias Header ‘${ech} “${E}]2;!:1${B}${N}”‘
alias IHeader ‘${ech} “${E}]1;!:1${B}${N}”‘
endif

# There are three different combinations:
# 1) A window on a remote machine
# 2) A window on my machine
# 3) A console on my machine

# test for each case:

if (${HOSTNAME} != $mymachine ) then
# it is a remote machine, therefore:
# window title has machinename and dirs
# icon has machine name only
# prompt has machine name+directory

alias setbar ‘Header “${HOSTNAME}: `dirs | ~/bin/Zappath`” ; IHeader ${HOSTNAME}’

# use either of these two lines to suit your tastes
# the first one shows the command number and full directory path
# The second shows just the hostname and the tail of the directory name

# alias SP ‘set prompt=”[!] ${HOSTNAME}:$cwd % “‘
alias SP ‘set prompt=”${HOSTNAME}:$cwd:t% “‘

else if ( `tty` == “/dev/console” ) then
goto getout
else if ( `tty` == “/dev/ttyp0” ) then

# in this case an assumption is made that the first pty
# window to appear is the console window.
# It’s not always true, but it usually works

# window title has <<CONSOLE>> and dirs
# icon has “console” only
# prompt has directory

alias setbar ‘Header “${console} `dirs | ~/bin/Zappath`”‘

# both of these works – pick one that suits you
# alias SP ‘set prompt=”[!] $cwd % “‘
alias SP ‘set prompt=”$cwd:t% “‘
else
# a plain window on my localhost
# window title has dirs
# icon has cwd only
# prompt has directory
# The next line must be one line, and not split onto two
alias setbar ‘Header “`dirs | ~/bin/Zappath `”; IHeader “`echo $cwd| ~/bin/Zappath`”‘
# alias SP ‘set prompt=”[!] $cwd % “‘
alias SP ‘set prompt=”$cwd:t% “‘
endif

# redo current window
alias . ‘dirs|~/bin/Zappath;setbar;jobs’

# change cd to change prompt, window and icon title
alias cd ‘chdir !*; SP;setbar’
alias pushd ‘pushd !*; SP;setbar’
alias popd ‘popd !*; SP;setbar’

SP;setbar
getout:
# end

Click here to get file: Header.csh

Other of my Unix shell tutorials can be found

Other of my Unix shell tutorials can be found here. Other shell tutorials can be found at Heiner’s SHELLdorado and Chris F. A. Johnson’s Unix Shell Page

[Update] csh – Unix, Linux Command | csh – POLLICELEE

csh – Unix, Linux Command



NAME

tcsh – C shell with file name completion and command line editing

SYNOPSIS

tcsh [-bcdefFimnqstvVxX] [-Dname[=value]] [arg …]
tcsh -l

DESCRIPTION

is an enhanced but completely compatible version of the Berkeley
UNIX C shell, (1).
It is a command language interpreter usable both as an interactive login
shell and a shell script command processor.
It includes a command-line editor (see The command-line editor),
programmable word completion (see Completion and listing),
spelling correction (see Spelling correction),
a history mechanism (see History substitution),
job control (see )
and a C-like syntax.
The NEW FEATURES section describes major enhancements of
over (1).
Throughout this manual, features of
not found in most (1) implementations
(specifically, the 4.4BSD )
are labeled with ‘(+)’, and features which are present in (1)
but not usually documented are labeled with ‘(u)’.

If the first argument (argument 0) to the shell is ‘-’ then it is a
login shell. A login shell can be also specified by invoking the shell with
the -l flag as the only argument.

tcsh – C shell with file name completion and command line editing] []] [arg …]is an enhanced but completely compatible version of the Berkeley UNIX C shell,(1). It is a command language interpreter usable both as an interactive login shell and a shell script command processor. It includes a command-line editor (see), programmable word completion (see), spelling correction (see), a history mechanism (see), job control (see) and a C-like syntax. Thesection describes major enhancements ofover(1). Throughout this manual, features ofnot found in most(1) implementations (specifically, the 4.4BSD) are labeled with ‘(+)’, and features which are present in(1) but not usually documented are labeled with ‘(u)’.If the first argument (argument 0) to the shell is ‘-’ then it is a login shell. A login shell can be also specified by invoking the shell with theflag as the only argument.

The rest of the flag arguments are interpreted as follows:

TagDescription

-b
Forces a ‘‘break’’ from option processing, causing any
further shell arguments to be treated as non-option arguments. The remaining
arguments will not be interpreted as shell options. This may be used to pass
options to a shell script without confusion or possible subterfuge. The shell
will not run a set-user ID script without this option.

-c
Commands are read from the following argument (which must be present, and
must be a single argument),
stored in the command shell variable for reference, and executed.
Any remaining arguments are placed in the argv shell variable.

-d
The shell loads the directory stack from as described under
Startup and shutdown, whether or not it is a login shell. (+)

-D[=]  
Sets the environment variable to . (Domain/OS only) (+)

-e
The shell exits if any invoked command terminates abnormally or
yields a non-zero exit status.

-f
The shell ignores , and thus starts faster.

-F
The shell uses (2) instead of (2) to spawn processes. (Convex/OS only) (+)

-i
The shell is interactive and prompts for its top-level input, even if
it appears to not be a terminal. Shells are interactive without this option if
their inputs and outputs are terminals.

-l
The shell is a login shell. Applicable only if -l is the only
flag specified.

-m
The shell loads even if it does not belong to the effective
user. Newer versions of (1) can pass -m to the shell. (+)

-n
The shell parses commands but does not execute them.
This aids in debugging shell scripts.

-q
The shell accepts SIGQUIT (see Signal handling) and behaves when
it is used under a debugger. Job control is disabled. (u)

-s
Command input is taken from the standard input.

-t
The shell reads and executes a single line of input. A ‘#146; may be used to
escape the newline at the end of this line and continue onto another line.

-v
Sets the verbose shell variable, so that
command input is echoed after history substitution.

-x
Sets the echo shell variable, so that commands are echoed
immediately before execution.

-V
Sets the verbose shell variable even before executing .

-X
Is to -x as -V is to -v.

–help  
Print a help message on the standard output and exit. (+)

–version  
Print the version/platform/compilation options on the standard output and exit.
This information is also contained in the version shell variable. (+)

After processing of flag arguments, if arguments remain but none of the
-c, -i, -s, or -t options were given, the first
argument is taken as the name of a file of commands, or ‘‘script’’, to
be executed. The shell opens this file and saves its name for possible
resubstitution by ‘$0’. Because many systems use either the standard
version 6 or version 7 shells whose shell scripts are not compatible
with this shell, the shell uses such a ‘standard’ shell to execute a script
whose first character is not a ‘#’, i.e., that does not start with a
comment.

After processing of flag arguments, if arguments remain but none of the, oroptions were given, the first argument is taken as the name of a file of commands, or ‘‘script’’, to be executed. The shell opens this file and saves its name for possible resubstitution by ‘$0’. Because many systems use either the standard version 6 or version 7 shells whose shell scripts are not compatible with this shell, the shell uses such a ‘standard’ shell to execute a script whose first character is not a ‘#’, i.e., that does not start with a comment.

Remaining arguments are placed in the argv shell variable.

A login shell begins by executing commands from the system files
and .
It then executes commands from files in the user’s home directory:
first (+)
or, if is not found, ,
then (or the value of the histfile shell variable),
then ,
and finally (or the value of the dirsfile shell variable) (+).
The shell may read before instead of after
, and before instead of after
or and , if so compiled;
see the version shell variable. (+)

A login shell begins by executing commands from the system filesand. It then executes commands from files in the user’sdirectory: first(+) or, ifis not found,, then(or the value of theshell variable), then, and finally(or the value of theshell variable) (+). The shell may readbefore instead of after, andbefore instead of afterorand, if so compiled; see theshell variable. (+)

Non-login shells read only and
or on startup.

For examples of startup files, please consult
.

Commands like (1) and (1),
which need be run only once per login, usually go in one’s file.
Users who need to use the same set of files with both (1) and
can have only a which checks for the existence of the
tcsh shell variable (q.v.) before using -specific commands,
or can have both a and a which s
(see the builtin command) .
The rest of this manual uses ‘’ to mean ‘ or,
if is not found, ’.

In the normal case, the shell begins reading commands from the terminal,
prompting with ‘> ’. (Processing of arguments and the use of the shell to
process files containing command scripts are described later.)
The shell repeatedly reads a line of command input, breaks it into words,
places it on the command history list, parses it and executes each command
in the line.

One can log out by typing ‘^D’ on an empty line, ‘logout’ or ‘login’ or
via the shell’s autologout mechanism (see the autologout shell variable).
When a login shell terminates it sets the logout shell variable to
‘normal’ or ‘automatic’ as appropriate, then
executes commands from the files
and . The shell may drop DTR on logout
if so compiled; see the version shell variable.

The names of the system login and logout files vary from system to system for
compatibility with different (1) variants; see FILES.

We first describe The command-line editor.
The Completion and listing and Spelling correction sections
describe two sets of functionality that are implemented as editor commands
but which deserve their own treatment.
Finally, Editor commands lists and describes
the editor commands specific to the shell and their default bindings.

Command-line input can be edited using key sequences much like those used in
GNU Emacs or (1).
The editor is active only when the edit shell variable is set, which
it is by default in interactive shells.
The builtin can display and change key bindings.
Emacs-style key bindings are used by default
(unless the shell was compiled otherwise; see the version shell variable),
but can change the key bindings to -style bindings en masse.

We first describe. Theandsections describe two sets of functionality that are implemented as editor commands but which deserve their own treatment. Finally,lists and describes the editor commands specific to the shell and their default bindings.Command-line input can be edited using key sequences much like those used in GNU Emacs or(1). The editor is active only when theshell variable is set, which it is by default in interactive shells. Thebuiltin can display and change key bindings. Emacs-style key bindings are used by default (unless the shell was compiled otherwise; see theshell variable), butcan change the key bindings to-style bindings en masse.

The shell always binds the arrow keys (as defined in the TERMCAP
environment variable) to

TagDescription

down

up

left

right

unless doing so would alter another single-character binding.
One can set the arrow key escape sequences to the empty string with
to prevent these bindings.
The ANSI/VT100 sequences for arrow keys are always bound.

Other key bindings are, for the most part, what Emacs and (1)
users would expect and can easily be displayed by , so there
is no need to list them here. Likewise, can list the editor
commands with a short description of each.

Note that editor commands do not have the same notion of a ‘‘word’’ as does the
shell. The editor delimits words with any non-alphanumeric characters not in
the shell variable wordchars, while the shell recognizes only whitespace
and some of the characters with special meanings to it, listed under
Lexical structure.

The shell is often able to complete words when given a unique abbreviation.
Type part of a word (for example ‘ls /usr/lost’) and hit the tab key to
run the editor command.
The shell completes the filename ‘/usr/lost’ to ‘/usr/lost+found/’,
replacing the incomplete word with the complete word in the input buffer.
(Note the terminal ‘/’; completion adds a ‘/’ to the
end of completed directories and a space to the end of other completed words,
to speed typing and provide a visual indicator of successful completion.
The addsuffix shell variable can be unset to prevent this.)
If no match is found (perhaps ‘/usr/lost+found’ doesn’t exist),
the terminal bell rings.
If the word is already complete (perhaps there is a ‘/usr/lost’ on your
system, or perhaps you were thinking too far ahead and typed the whole thing)
a ‘/’ or space is added to the end if it isn’t already there.

The shell is often able to complete words when given a unique abbreviation. Type part of a word (for example ‘ls /usr/lost’) and hit the tab key to run theeditor command. The shell completes the filename ‘/usr/lost’ to ‘/usr/lost+found/’, replacing the incomplete word with the complete word in the input buffer. (Note the terminal ‘/’; completion adds a ‘/’ to the end of completed directories and a space to the end of other completed words, to speed typing and provide a visual indicator of successful completion. Theshell variable can be unset to prevent this.) If no match is found (perhaps ‘/usr/lost+found’ doesn’t exist), the terminal bell rings. If the word is already complete (perhaps there is a ‘/usr/lost’ on your system, or perhaps you were thinking too far ahead and typed the whole thing) a ‘/’ or space is added to the end if it isn’t already there.

Completion works anywhere in the line, not at just the end; completed
text pushes the rest of the line to the right. Completion in the middle of a word
often results in leftover characters to the right of the cursor that need
to be deleted.

Commands and variables can be completed in much the same way.
For example, typing ‘em[tab]’ would complete ‘em’ to
‘emacs’ if were the only command on your system beginning with ‘em’.
Completion can find a command in any directory in path or if
given a full pathname.
Typing ‘echo $ar[tab]’ would complete ‘$ar’ to ‘$argv’
if no other variable began with ‘ar’.

The shell parses the input buffer to determine whether the word you want to
complete should be completed as a filename, command or variable.
The first word in the buffer and the first word following
‘;’, ‘|’, ‘|&’, ‘&&’ or ‘||’ is considered to be a command.
A word beginning with ‘$’ is considered to be a variable.
Anything else is a filename. An empty line is ‘completed’ as a filename.

You can list the possible completions of a word at any time by typing ‘^D’
to run the editor command.
The shell lists the possible completions using the builtin (q.v.)
and reprints the prompt and unfinished command line, for example:

TagDescription

> ls /usr/l[^D]

lbin/ lib/ local/ lost+found/

> ls /usr/l

If the autolist shell variable is set, the shell lists the remaining
choices (if any) whenever completion fails:

TagDescription

> set autolist

> nm /usr/lib/libt[tab]

libtermcap.a@ libtermlib.a@

> nm /usr/lib/libterm

If autolist is set to ‘ambiguous’, choices are listed only when
completion fails and adds no new characters to the word being completed.

If theshell variable is set, the shell lists the remaining choices (if any) whenever completion fails:Ifis set to ‘ambiguous’, choices are listed only when completion fails and adds no new characters to the word being completed.

A filename to be completed can contain variables, your own or others’ home
directories abbreviated with ‘~’ (see Filename substitution) and
directory stack entries abbreviated with ‘=’
(see Directory stack substitution). For example,

TagDescription

> ls ~k[^D]

kahn kas kellogg

> ls ~ke[tab]

> ls ~kellogg/

or

TagDescription

> set local = /usr/local

> ls $lo[tab]

> ls $local/[^D]

bin/ etc/ lib/ man/ src/

> ls $local/

Note that variables can also be expanded explicitly with the
editor command.

orNote that variables can also be expanded explicitly with theeditor command.

lists at only the end of the line;
in the middle of a line it deletes the character under the cursor and
on an empty line it logs one out or, if ignoreeof is set, does nothing.
‘M-^D’, bound to the editor command , lists completion
possibilities anywhere on a line, and (or any one of the
related editor commands that do or don’t delete, list and/or log out,
listed under ) can be bound to ‘^D’ with
the builtin command if so desired.

The and editor commands
(not bound to any keys by default) can be used to cycle up and down through
the list of possible completions, replacing the current word with the next or
previous word in the list.

The shell variable fignore can be set to a list of suffixes to be
ignored by completion. Consider the following:

TagDescription

> ls

Makefile condiments.h~ main.o side.c

README main.c meal side.o

condiments.h main.c~

> set fignore = (.o \~)

> emacs ma[^D]

main.c main.c~ main.o

> emacs ma[tab]

> emacs main.c

‘main.c~’ and ‘main.o’ are ignored by completion (but not listing),
because they end in suffixes in fignore.
Note that a ‘#146; was needed in front of ‘~’ to prevent it from being
expanded to home as described under Filename substitution.
fignore is ignored if only one completion is possible.

‘main.c~’ and ‘main.o’ are ignored by completion (but not listing), because they end in suffixes in. Note that a ‘#146; was needed in front of ‘~’ to prevent it from being expanded toas described underis ignored if only one completion is possible.

If the complete shell variable is set to ‘enhance’, completion
1) ignores case and 2) considers periods, hyphens and underscores
(‘.’, ‘-’ and ‘_’) to be word separators and hyphens and underscores to
be equivalent. If you had the following files

TagDescription

comp.lang.c comp.lang.perl comp.std.c++

comp.lang.c++ comp.std.c

and typed ‘mail -f c.l.c[tab]’, it would be completed to
‘mail -f comp.lang.c’, and ^D would list ‘comp.lang.c’ and ‘comp.lang.c++’.
‘mail -f c..c++[^D]’ would list ‘comp.lang.c++’ and ‘comp.std.c++’. Typing
‘rm a–file[^D]’ in the following directory

TagDescription

A_silly_file a-hyphenated-file another_silly_file

would list all three files, because case is ignored and hyphens and
underscores are equivalent. Periods, however, are not equivalent to
hyphens or underscores.

and typed ‘mail -f c.l.c[tab]’, it would be completed to ‘mail -f comp.lang.c’, and ^D would list ‘comp.lang.c’ and ‘comp.lang.c++’. ‘mail -f c..c++[^D]’ would list ‘comp.lang.c++’ and ‘comp.std.c++’. Typing ‘rm a–file[^D]’ in the following directorywould list all three files, because case is ignored and hyphens and underscores are equivalent. Periods, however, are not equivalent to hyphens or underscores.

Completion and listing are affected by several other shell variables:
recexact can be set to complete on the shortest possible unique
match, even if more typing might result in a longer match:

TagDescription

> ls

fodder foo food foonly

> set recexact

> rm fo[tab]

just beeps, because ‘fo’ could expand to ‘fod’ or ‘foo’, but if we type
another ‘o’,

TagDescription

> rm foo[tab]

> rm foo

the completion completes on ‘foo’, even though ‘food’ and ‘foonly’
also match.
autoexpand can be set to run the editor command
before each completion attempt, autocorrect can be set to
spelling-correct the word to be completed (see Spelling correction)
before each completion attempt and correct can be set to complete
commands automatically after one hits ‘return’.
matchbeep can be set to make completion beep or not beep in a variety
of situations, and nobeep can be set to never beep at all.
nostat can be set to a list of directories and/or patterns that
match directories to prevent the completion mechanism from (2)ing
those directories.
listmax and listmaxrows can be set to limit the number of items
and rows (respectively) that are listed without asking first.
recognize_only_executables can be set to make the shell list only
executables when listing commands, but it is quite slow.

just beeps, because ‘fo’ could expand to ‘fod’ or ‘foo’, but if we type another ‘o’,the completion completes on ‘foo’, even though ‘food’ and ‘foonly’ also match.can be set to run theeditor command before each completion attempt,can be set to spelling-correct the word to be completed (see) before each completion attempt andcan be set to complete commands automatically after one hits ‘return’.can be set to make completion beep or not beep in a variety of situations, andcan be set to never beep at all.can be set to a list of directories and/or patterns that match directories to prevent the completion mechanism from(2)ing those directories.andcan be set to limit the number of items and rows (respectively) that are listed without asking first.can be set to make the shell list only executables when listing commands, but it is quite slow.

Finally, the builtin command can be used to tell the shell how
to complete words other than filenames, commands and variables.
Completion and listing do not work on glob-patterns (see Filename substitution),
but the and editor commands perform
equivalent functions for glob-patterns.

The shell can sometimes correct the spelling of filenames, commands and variable names
as well as completing and listing them.

The shell can sometimes correct the spelling of filenames, commands and variable names as well as completing and listing them.

Individual words can be spelling-corrected with the
editor command (usually bound to M-s and M-S)
and the entire input buffer with (usually bound to M-$).
The correct shell variable can be set to ‘cmd’ to correct the
command name or ‘all’ to correct the entire line each time return is typed,
and autocorrect can be set to correct the word to be completed
before each completion attempt.

When spelling correction is invoked in any of these ways and
the shell thinks that any part of the command line is misspelled,
it prompts with the corrected line:

TagDescription

> set correct = cmd

> lz /usr/bin

CORRECT>ls /usr/bin (y|n|e|a)?

One can answer ‘y’ or space to execute the corrected line,
‘e’ to leave the uncorrected command in the input buffer,
‘a’ to abort the command as if ‘^C’ had been hit, and
anything else to execute the original line unchanged.

One can answer ‘y’ or space to execute the corrected line, ‘e’ to leave the uncorrected command in the input buffer, ‘a’ to abort the command as if ‘^C’ had been hit, and anything else to execute the original line unchanged.

Spelling correction recognizes user-defined completions (see the
builtin command). If an input word in a position for
which a completion is defined resembles a word in the completion list,
spelling correction registers a misspelling and suggests the latter
word as a correction. However, if the input word does not match any of
the possible completions for that position, spelling correction does
not register a misspelling.

Like completion, spelling correction works anywhere in the line,
pushing the rest of the line to the right and possibly leaving
extra characters to the right of the cursor.

Beware: spelling correction is not guaranteed to work the way one intends,
and is provided mostly as an experimental feature.
Suggestions and improvements are welcome.

‘bindkey’ lists key bindings and ‘bindkey -l’ lists and briefly describes
editor commands.
Only new or especially interesting editor commands are described here.
See (1) and (1) for descriptions of each editor’s
key bindings.

‘bindkey’ lists key bindings and ‘bindkey -l’ lists and briefly describes editor commands. Only new or especially interesting editor commands are described here. See(1) and(1) for descriptions of each editor’s key bindings.

The character or characters to which each command is bound by default is
given in parentheses. ‘^’ means a control character and
‘M-’ a meta character, typed as escape-
on terminals without a meta key. Case counts, but commands that are bound
to letters by default are bound to both lower- and uppercase letters for
convenience.

TagDescription

complete-word (tab)  
Completes a word as described under Completion and listing.

complete-word-back (not bound)  
Like , but steps up from the end of the list.

complete-word-fwd (not bound)  
Replaces the current word with the first word in the list of possible
completions. May be repeated to step down through the list.
At the end of the list, beeps and reverts to the incomplete word.

complete-word-raw (^X-tab)  
Like , but ignores user-defined completions.

copy-prev-word (M-^_)  
Copies the previous word in the current line into the input buffer.
See also .

dabbrev-expand (M-/)  
Expands the current word to the most recent preceding one for which
the current is a leading substring, wrapping around the history list
(once) if necessary.
Repeating without any intervening typing
changes to the next previous word etc., skipping identical matches
much like does.

delete-char (not bound)  
Deletes the character under the cursor.
See also .

delete-char-or-eof (not bound)  
Does if there is a character under the cursor
or on an empty line.
See also .

delete-char-or-list (not bound)  
Does if there is a character under the cursor
or at the end of the line.
See also .

delete-char-or-list-or-eof (^D)  
Does if there is a character under the cursor,
at the end of the line
or on an empty line.
See also those three commands, each of which does only a single action, and
, and ,
each of which does a different two out of the three.

down-history (down-arrow, ^N)  
Like , but steps down, stopping at the original input line.

end-of-file (not bound)  
Signals an end of file, causing the shell to exit unless the ignoreeof
shell variable (q.v.) is set to prevent this.
See also .

expand-history (M-space)  
Expands history substitutions in the current word.
See History substitution.
See also , and
the autoexpand shell variable.

expand-glob (^X-*)  
Expands the glob-pattern to the left of the cursor.
See Filename substitution.

expand-line (not bound)  
Like , but
expands history substitutions in each word in the input buffer,

expand-variables (^X-$)  
Expands the variable to the left of the cursor.
See Variable substitution.

history-search-backward (M-p, M-P)  
Searches backwards through the history list for a command beginning with
the current contents of the input buffer up to the cursor and copies it
into the input buffer.
The search string may be a glob-pattern (see Filename substitution)
containing ‘*’, ‘?’, ‘[]’ or ‘{}’.
and will proceed from the
appropriate point in the history list.
Emacs mode only.
See also and .

history-search-forward (M-n, M-N)  
Like , but searches forward.

i-search-back (not bound)  
Searches backward like , copies the first match
into the input buffer with the cursor positioned at the end of the pattern,
and prompts with ‘bck: ’ and the first match. Additional characters may be
typed to extend the search, may be typed to continue
searching with the same pattern, wrapping around the history list if
necessary, ( must be bound to a
single character for this to work) or one of the following special characters
may be typed:

TagDescription
 

TagDescription

^W

Appends the rest of the word under the cursor to the search pattern.

delete (or any character bound to )
 
Undoes the effect of the last character typed and deletes a character
from the search pattern if appropriate.

^G

If the previous search was successful, aborts the entire search.
If not, goes back to the last successful search.

escape

Ends the search, leaving the current line in the input buffer.

Any other character not bound to terminates the
search, leaving the current line in the input buffer, and
is then interpreted as normal input. In particular, a carriage return
causes the current line to be executed.
Emacs mode only.
See also and .

i-search-fwd (not bound)  
Like , but searches forward.

insert-last-word (M-_)  
Inserts the last word of the previous input line (‘!$’) into the input buffer.
See also .

list-choices (M-^D)  
Lists completion possibilities as described under Completion and listing.
See also and .

list-choices-raw (^X-^D)  
Like , but ignores user-defined completions.

list-glob (^X-g, ^X-G)  
Lists (via the builtin) matches to the glob-pattern
(see Filename substitution) to the left of the cursor.

list-or-eof (not bound)  
Does
or on an empty line.
See also .

magic-space (not bound)  
Expands history substitutions in the current line,
like , and inserts a space.
is designed to be bound to the space bar,
but is not bound by default.

normalize-command (^X-?)  
Searches for the current word in PATH and, if it is found, replaces it with
the full path to the executable. Special characters are quoted. Aliases are
expanded and quoted but commands within aliases are not. This command is
useful with commands that take commands as arguments, e.g., ‘dbx’ and ‘sh -x’.

normalize-path (^X-n, ^X-N)  
Expands the current word as described under the ‘expand’ setting
of the symlinks shell variable.

overwrite-mode (unbound)  
Toggles between input and overwrite modes.

run-fg-editor (M-^Z)  
Saves the current input line and
looks for a stopped job with a name equal to the last component of the
file name part of the EDITOR or VISUAL environment variables,
or, if neither is set, ‘ed’ or ‘vi’.
If such a job is found, it is restarted as if ‘fg %’ had been
typed. This is used to toggle back and forth between an editor and
the shell easily. Some people bind this command to ‘^Z’ so they
can do this even more easily.

run-help (M-h, M-H)  
Searches for documentation on the current command, using the same notion of
‘current command’ as the completion routines, and prints it. There is no way
to use a pager; is designed for short help files.
If the special alias helpcommand is defined, it is run with the
command name as a sole argument. Else,
documentation should be in a file named .help, .1,
.6, .8 or , which should be in one
of the directories listed in the HPATH environment variable.
If there is more than one help file only the first is printed.

self-insert-command (text characters)  
In insert mode (the default), inserts the typed character into the input line after the character under the cursor.
In overwrite mode, replaces the character under the cursor with the typed character.
The input mode is normally preserved between lines, but the
inputmode shell variable can be set to ‘insert’ or ‘overwrite’ to put the
editor in that mode at the beginning of each line.
See also .

sequence-lead-in (arrow prefix, meta prefix, ^X)  
Indicates that the following characters are part of a
multi-key sequence. Binding a command to a multi-key sequence really creates
two bindings: the first character to and the
whole sequence to the command. All sequences beginning with a character
bound to are effectively bound to
unless bound to another command.

spell-line (M-$)  
Attempts to correct the spelling of each word in the input buffer, like
, but ignores words whose first character is one of
‘-’, ‘!’, ‘^’ or ‘%’, or which contain ‘#146;, ‘*’ or ‘?’, to avoid problems
with switches, substitutions and the like.
See Spelling correction.

spell-word (M-s, M-S)  
Attempts to correct the spelling of the current word as described
under Spelling correction.
Checks each component of a word which appears to be a pathname.

toggle-literal-history (M-r, M-R)  
Expands or ‘unexpands’ history substitutions in the input buffer.
See also and the autoexpand shell variable.

undefined-key (any unbound key)  
Beeps.

up-history (up-arrow, ^P)  
Copies the previous entry in the history list into the input buffer.
If histlit is set, uses the literal form of the entry.
May be repeated to step up through the history list, stopping at the top.

vi-search-back (?)  
Prompts with ‘?’ for a search string (which may be a glob-pattern, as with
), searches for it and copies it into the
input buffer. The bell rings if no match is found.
Hitting return ends the search and leaves the last match in the input
buffer.
Hitting escape ends the search and executes the match.
mode only.

vi-search-fwd (/)  
Like , but searches forward.

which-command (M-?)  
Does a (see the description of the builtin command) on the
first word of the input buffer.

yank-pop (M-y)  
When executed immediately after a or another ,
replaces the yanked string with the next previous string from the
killring. This also has the effect of rotating the killring, such that
this string will be considered the most recently killed by a later
command. Repeating will cycle through the
killring any number of times.

The shell splits input lines into words at blanks and tabs. The special
characters ‘&’, ‘|’, ‘;’, ‘<’, ‘>’, ‘(’, and ‘)’ and the doubled characters
‘&&’, ‘||’, ‘<<’ and ‘>>’ are always separate words, whether or not they are
surrounded by whitespace.

The shell splits input lines into words at blanks and tabs. The special characters ‘&’, ‘|’, ‘;’, ‘’, ‘(’, and ‘)’ and the doubled characters ‘&&’, ‘||’, ‘<>’ are always separate words, whether or not they are surrounded by whitespace.

When the shell’s input is not a terminal, the character ‘#’ is taken to begin a
comment. Each ‘#’ and the rest of the input line on which it appears is
discarded before further parsing.

A special character (including a blank or tab) may be prevented from having
its special meaning, and possibly made part of another word, by preceding it
with a backslash (‘#146;) or enclosing it in single (‘’’), double (‘”’) or
backward (‘‘’) quotes. When not otherwise quoted a newline preceded by a ‘#146;
is equivalent to a blank, but inside quotes this sequence results in a
newline.

Furthermore, all Substitutions (see below) except History substitution
can be prevented by enclosing the strings (or parts of strings)
in which they appear with single quotes or by quoting the crucial character(s)
(e.g., ‘$’ or ‘‘’ for Variable substitution or Command substitution respectively)
with ‘#146;. (Alias substitution is no exception: quoting in any way any
character of a word for which an has been defined prevents
substitution of the alias. The usual way of quoting an alias is to precede it
with a backslash.) History substitution is prevented by
backslashes but not by single quotes. Strings quoted with double or backward
quotes undergo Variable substitution and Command substitution, but other
substitutions are prevented.

Text inside single or double quotes becomes a single word (or part of one).
Metacharacters in these strings, including blanks and tabs, do not form
separate words. Only in one special case (see Command substitution
below) can a double-quoted string yield parts of more than one word;
single-quoted strings never do. Backward quotes are special: they signal
Command substitution (q.v.), which may result in more than one word.

Quoting complex strings, particularly strings which themselves contain quoting
characters, can be confusing. Remember that quotes need not be used as they are
in human writing! It may be easier to quote not an entire string, but only
those parts of the string which need quoting, using different types of quoting
to do so if appropriate.

The backslash_quote shell variable (q.v.) can be set to make backslashes
always quote ‘#146;, ‘’’, and ‘”’. (+) This may make complex quoting tasks
easier, but it can cause syntax errors in (1) scripts.

We now describe the various transformations the shell performs on the input in
the order in which they occur. We note in passing the data structures involved
and the commands and variables which affect them. Remember that substitutions
can be prevented by quoting as described under Lexical structure.

Each command, or ‘‘event’’, input from the terminal is saved in the history
list. The previous command is always saved, and the history shell
variable can be set to a number to save that many commands. The histdup
shell variable can be set to not save duplicate events or consecutive duplicate
events.

We now describe the various transformations the shell performs on the input in the order in which they occur. We note in passing the data structures involved and the commands and variables which affect them. Remember that substitutions can be prevented by quoting as described underEach command, or ‘‘event’’, input from the terminal is saved in the history list. The previous command is always saved, and theshell variable can be set to a number to save that many commands. Theshell variable can be set to not save duplicate events or consecutive duplicate events.

Saved commands are numbered sequentially from 1 and stamped with the time.
It is not usually necessary to use event numbers, but the current event number
can be made part of the prompt by placing an ‘!’ in the prompt shell variable.

The shell actually saves history in expanded and literal (unexpanded) forms.
If the histlit shell variable is set, commands that display and store
history use the literal form.

The builtin command can print, store in a file, restore
and clear the history list at any time,
and the savehist and histfile shell variables can be can be set to
store the history list automatically on logout and restore it on login.

History substitutions introduce words from the history list into the input
stream, making it easy to repeat commands, repeat arguments of a previous
command in the current command, or fix spelling mistakes in the previous
command with little typing and a high degree of confidence.

History substitutions begin with the character ‘!’. They may begin anywhere in
the input stream, but they do not nest. The ‘!’ may be preceded by a ‘#146; to
prevent its special meaning; for convenience, a ‘!’ is passed unchanged when it
is followed by a blank, tab, newline, ‘=’ or ‘(’. History substitutions also
occur when an input line begins with ‘^’. This special abbreviation will be
described later. The characters used to signal history substitution (‘!’ and
‘^’) can be changed by setting the histchars shell variable. Any input
line which contains a history substitution is printed before it is executed.

A history substitution may have an ‘‘event specification’’, which indicates
the event from which words are to be taken, a ‘‘word designator’’,
which selects particular words from the chosen event, and/or a ‘‘modifier’’,
which manipulates the selected words.

An event specification can be

TagDescription

A number, referring to a particular event

An offset, referring to the event before the current event

#

The current event.
This should be used carefully in (1), where there is no check for
recursion. allows 10 levels of recursion. (+)

!

The previous event (equivalent to ‘-1’)

The most recent event whose first word begins with the string

??

The most recent event which contains the string .
The second ‘?’ can be omitted if it is immediately followed by a newline.

For example, consider this bit of someone’s history list:

TagDescription

9 8:30 nroff -man wumpus.man

10 8:31 cp wumpus.man wumpus.man.old

11 8:36 vi wumpus.man

12 8:37 diff wumpus.man.old wumpus.man

The commands are shown with their event numbers and time stamps.
The current event, which we haven’t typed in yet, is event 13.
‘!11’ and ‘!-2’ refer to event 11.
‘!!’ refers to the previous event, 12. ‘!!’ can be abbreviated ‘!’ if it is
followed by ‘:’ (‘:’ is described below).
‘!n’ refers to event 9, which begins with ‘n’.
‘!?old?’ also refers to event 12, which contains ‘old’.
Without word designators or modifiers history references simply expand to the
entire event, so we might type ‘!cp’ to redo the copy command or ‘!!|more’
if the ‘diff’ output scrolled off the top of the screen.

The commands are shown with their event numbers and time stamps. The current event, which we haven’t typed in yet, is event 13. ‘!11’ and ‘!-2’ refer to event 11. ‘!!’ refers to the previous event, 12. ‘!!’ can be abbreviated ‘!’ if it is followed by ‘:’ (‘:’ is described below). ‘!n’ refers to event 9, which begins with ‘n’. ‘!?old?’ also refers to event 12, which contains ‘old’. Without word designators or modifiers history references simply expand to the entire event, so we might type ‘!cp’ to redo the copy command or ‘!!|more’ if the ‘diff’ output scrolled off the top of the screen.

History references may be insulated from the surrounding text with braces if
necessary. For example, ‘!vdoc’ would look for a command beginning with
‘vdoc’, and, in this example, not find one, but ‘!{v}doc’ would expand
unambiguously to ‘vi wumpus.mandoc’.
Even in braces, history substitutions do not nest.

(+) While (1) expands, for example, ‘!3d’ to event 3 with the
letter ‘d’ appended to it, expands it to the last event beginning
with ‘3d’; only completely numeric arguments are treated as event numbers.
This makes it possible to recall events beginning with numbers.
To expand ‘!3d’ as in (1) say ‘!\3d’.

To select words from an event we can follow the event specification by a ‘:’
and a designator for the desired words. The words of an input line are
numbered from 0, the first (usually command) word being 0, the second word
(first argument) being 1, etc. The basic word designators are:

TagDescription

0

The first (command) word

The th argument

^

The first argument, equivalent to ‘1’

$

The last argument

%

The word matched by an ?? search

A range of words

Equivalent to

*

Equivalent to ‘^-$’, but returns nothing if the event contains only 1 word

Equivalent to

Equivalent to , but omitting the last word (‘$’)

Selected words are inserted into the command line separated by single blanks.
For example, the ‘diff’ command in the previous example might have been
typed as ‘diff !!:1.old !!:1’ (using ‘:1’ to select the first argument
from the previous event) or ‘diff !-2:2 !-2:1’ to select and swap the
arguments from the ‘cp’ command. If we didn’t care about the order of the
‘diff’ we might have said ‘diff !-2:1-2’ or simply ‘diff !-2:*’.
The ‘cp’ command might have been written ‘cp wumpus.man !#:1.old’, using ‘#’
to refer to the current event.
‘!n:- hurkle.man’ would reuse the first two words from the ‘nroff’ command
to say ‘nroff -man hurkle.man’.

The ‘:’ separating the event specification from the word designator can be
omitted if the argument selector begins with a ‘^’, ‘$’, ‘*’, ‘%’ or ‘-’.
For example, our ‘diff’ command might have been ‘diff !!^.old !!^’ or,
equivalently, ‘diff !!$.old !!$’. However, if ‘!!’ is abbreviated ‘!’,
an argument selector beginning with ‘-’ will be interpreted as an event
specification.

A history reference may have a word designator but no event specification.
It then references the previous command.
Continuing our ‘diff’ example, we could have said simply ‘diff
!^.old !^’ or, to get the arguments in the opposite order, just ‘diff !*’.

The word or words in a history reference can be edited, or ‘‘modified’’,
by following it with one or more modifiers, each preceded by a ‘:’:

TagDescription

h

Remove a trailing pathname component, leaving the head.

t

Remove all leading pathname components, leaving the tail.

r

Remove a filename extension ‘.xxx’, leaving the root name.

e

Remove all but the extension.

u

Uppercase the first lowercase letter.

l

Lowercase the first uppercase letter.

s

Substitute for .
is simply a string like , not a regular expression as in
the eponymous (1) command.
Any character may be used as the delimiter in place of ‘/’;
a ‘#146; can be used to quote the delimiter inside and .
The character ‘&’ in the is replaced by ; ‘#146; also quotes ‘&’.
If is empty (‘‘’’), the from a previous substitution or the
from a previous ‘??’ event specification is used.
The trailing delimiter may be omitted if it is immediately followed by a newline.

&

Repeat the previous substitution.

g

Apply the following modifier once to each word.

a (+)

Apply the following modifier as many times as possible to a single word.
‘a’ and ‘g’ can be used together to apply a modifier globally.
In the current implementation, using the ‘a’ and ‘s’ modifiers together can
lead to an infinite loop. For example, ‘:as/f/ff/’ will never terminate.
This behavior might change in the future.

p

Print the new command line but do not execute it.

q

Quote the substituted words, preventing further substitutions.

x

Like q, but break into words at blanks, tabs and newlines.

Modifiers are applied to only the first modifiable word (unless ‘g’ is used).
It is an error for no word to be modifiable.

For example, the ‘diff’ command might have been written as ‘diff wumpus.man.old
!#^:r’, using ‘:r’ to remove ‘.old’ from the first argument on the same line
(‘!#^’). We could say ‘echo hello out there’, then ‘echo !*:u’ to capitalize
‘hello’, ‘echo !*:au’ to say it out loud, or ‘echo !*:agu’ to really shout.
We might follow ‘mail -s “I forgot my password” rot’ with ‘!:s/rot/root’ to
correct the spelling of ‘root’ (but see Spelling correction for a
different approach).

There is a special abbreviation for substitutions.
‘^’, when it is the first character on an input line, is equivalent to ‘!:s^’.
Thus we might have said ‘^rot^root’ to make the spelling correction in the
previous example.
This is the only history substitution which does not explicitly begin with ‘!’.

(+) In as such, only one modifier may be applied to each history
or variable expansion. In , more than one may be used, for example

TagDescription

% mv wumpus.man /usr/man/man1/wumpus.1

% man !$:t:r

man wumpus

In , the result would be ‘wumpus.1:r’. A substitution followed by a
colon may need to be insulated from it with braces:

TagDescription

> mv a.out /usr/games/wumpus

> setenv PATH !$:h:$PATH

Bad ! modifier: $.

> setenv PATH !{-2$:h}:$PATH

setenv PATH /usr/games:/bin:/usr/bin:.

The first attempt would succeed in but fails in ,
because expects another modifier after the second colon
rather than ‘$’.

In, the result would be ‘wumpus.1:r’. A substitution followed by a colon may need to be insulated from it with braces:The first attempt would succeed inbut fails in, becauseexpects another modifier after the second colon rather than ‘$’.

Finally, history can be accessed through the editor as well as through
the substitutions just described.
The and , and
, and ,
and ,
and editor commands search for
events in the history list and copy them into the input buffer.
The editor command switches between the
expanded and literal forms of history lines in the input buffer.
and expand history substitutions
in the current word and in the entire input buffer respectively.

The shell maintains a list of aliases which can be set, unset and printed by
the and commands. After a command line is parsed
into simple commands (see ) the first word of each command,
left-to-right, is checked to see if it has an alias. If so, the first word is
replaced by the alias. If the alias contains a history reference, it undergoes
History substitution (q.v.) as though the original command were the
previous input line. If the alias does not contain a history reference, the
argument list is left untouched.

The shell maintains a list of aliases which can be set, unset and printed by theandcommands. After a command line is parsed into simple commands (see) the first word of each command, left-to-right, is checked to see if it has an alias. If so, the first word is replaced by the alias. If the alias contains a history reference, it undergoes(q.v.) as though the original command were the previous input line. If the alias does not contain a history reference, the argument list is left untouched.

Thus if the alias for ‘ls’ were ‘ls -l’ the command ‘ls /usr’ would become ‘ls
-l /usr’, the argument list here being undisturbed. If the alias for ‘lookup’
were ‘grep !^ /etc/passwd’ then ‘lookup bill’ would become ‘grep bill
/etc/passwd’. Aliases can be used to introduce parser metasyntax. For
example, ‘alias print ’pr \!* | lpr’’ defines a ‘‘command’’ (‘print’) which
(1)s its arguments to the line printer.

Alias substitution is repeated until the first word of the command has no
alias. If an alias substitution does not change the first word (as in the
previous example) it is flagged to prevent a loop. Other loops are detected and
cause an error.

Some aliases are referred to by the shell; see Special aliases.

The shell maintains a list of variables, each of which has as value a list of
zero or more words.
The values of shell variables can be displayed and changed with the
and commands.
The system maintains its own list of ‘‘environment’’ variables.
These can be displayed and changed with , and
.

The shell maintains a list of variables, each of which has as value a list of zero or more words. The values of shell variables can be displayed and changed with theandcommands. The system maintains its own list of ‘‘environment’’ variables. These can be displayed and changed withand

(+) Variables may be made read-only with ‘set -r’ (q.v.)
Read-only variables may not be modified or unset;
attempting to do so will cause an error.
Once made read-only, a variable cannot be made writable,
so ‘set -r’ should be used with caution.
Environment variables cannot be made read-only.

Some variables are set by the shell or referred to by it.
For instance, the argv variable is an image of the shell’s argument
list, and words of this variable’s value are referred to in special ways.
Some of the variables referred to by the shell are toggles;
the shell does not care what their value is, only whether they are set or not.
For instance, the verbose variable is a toggle which causes command
input to be echoed. The -v command line option sets this variable.
Special shell variables lists all variables which are referred to by the shell.

Other operations treat variables numerically. The ‘@’ command permits numeric
calculations to be performed and the result assigned to a variable. Variable
values are, however, always represented as (zero or more) strings. For the
purposes of numeric operations, the null string is considered to be zero, and
the second and subsequent words of multi-word values are ignored.

After the input line is aliased and parsed, and before each command is
executed, variable substitution is performed keyed by ‘$’ characters. This
expansion can be prevented by preceding the ‘$’ with a ‘\’ except within ‘”’s
where it occurs, and within ‘’’s where it occurs.
Strings quoted by ‘‘’ are interpreted later (see Command substitution
below) so ‘$’ substitution does not occur there until later,
if at all. A ‘$’ is passed unchanged if followed by a blank, tab, or
end-of-line.

Input/output redirections are recognized before variable expansion, and are
variable expanded separately. Otherwise, the command name and entire argument
list are expanded together. It is thus possible for the first (command) word
(to this point) to generate more than one word, the first of which becomes the
command name, and the rest of which become arguments.

Unless enclosed in ‘”’ or given the ‘:q’ modifier the results of variable
substitution may eventually be command and filename substituted. Within ‘”’, a
variable whose value consists of multiple words expands to a (portion of a)
single word, with the words of the variable’s value separated by blanks. When
the ‘:q’ modifier is applied to a substitution the variable will expand to
multiple words with each word separated by a blank and quoted to prevent later
command or filename substitution.

The following metasequences are provided for introducing variable values into
the shell input. Except as noted, it is an error to reference a variable which
is not set.

$

TagDescription

${}

Substitutes the words of the value of variable , each separated
by a blank. Braces insulate from following characters which would
otherwise be part of it. Shell variables have names consisting of up to 20
letters and digits starting with a letter. The underscore character is
considered a letter. If is not a shell variable, but is set in the
environment, then that value is returned (but ‘:’ modifiers and the other forms
given below are not available in this case).

$[]

${[]}
 
Substitutes only the selected words from the value of .
The is subjected to ‘$’ substitution and may consist of
a single number or two numbers separated by a ‘-’.
The first word of a variable’s value is numbered ‘1’.
If the first number of a range is omitted it defaults to ‘1’.
If the last member of a range is omitted it defaults to ‘$#’.
The ‘*’ selects all words.
It is not an error for a range to be empty if the
second argument is omitted or in range.

$0

Substitutes the name of the file from which command input
is being read. An error occurs if the name is not known.

$

${}
 
Equivalent to ‘$argv[]’.

$*

Equivalent to ‘$argv’, which is equivalent to ‘$argv[*]’.

The ‘:’ modifiers described under History substitution, except for ‘:p’,
can be applied to the substitutions above. More than one may be used. (+)
Braces may be needed to insulate a variable substitution from a literal colon
just as with History substitution (q.v.); any modifiers must appear
within the braces.

The following substitutions can not be modified with ‘:’ modifiers.

$?

${?}

Substitutes the string ‘1’ if is set, ‘0’ if it is not.

$?0

Substitutes ‘1’ if the current input filename is known, ‘0’ if it is not.
Always ‘0’ in interactive shells.

$#

${#}

Substitutes the number of words in .

$#

Equivalent to ‘$#argv’. (+)

$%

${%}

Substitutes the number of characters in . (+)

$%

${%}
 
Substitutes the number of characters in $argv[]. (+)

$?

Equivalent to ‘$status’. (+)

$$

Substitutes the (decimal) process number of the (parent) shell.

$!

Substitutes the (decimal) process number of the last
background process started by this shell. (+)

$_

Substitutes the command line of the last command executed. (+)

$<

Substitutes a line from the standard input, with no further interpretation
thereafter. It can be used to read from the keyboard in a shell script.
(+) While always quotes $<, as if it were equivalent to ‘$<:q’,
does not. Furthermore, when is waiting for a line to be
typed the user may type an interrupt to interrupt the sequence into
which the line is to be substituted, but does not allow this.

The editor command , normally bound to ‘^X-$’,
can be used to interactively expand individual variables.

The remaining substitutions are applied selectively to the arguments of builtin
commands. This means that portions of expressions which are not evaluated are
not subjected to these expansions. For commands which are not internal to the
shell, the command name is substituted separately from the argument list. This
occurs very late, after input-output redirection is performed, and in a child
of the main shell.

Command substitution is indicated by a command enclosed in ‘‘’. The output
from such a command is broken into separate words at blanks, tabs and newlines,
and null words are discarded. The output is variable and command substituted
and put in place of the original string.

The editor command, normally bound to ‘^X-$’, can be used to interactively expand individual variables.The remaining substitutions are applied selectively to the arguments of builtin commands. This means that portions of expressions which are not evaluated are not subjected to these expansions. For commands which are not internal to the shell, the command name is substituted separately from the argument list. This occurs very late, after input-output redirection is performed, and in a child of the main shell.Command substitution is indicated by a command enclosed in ‘‘’. The output from such a command is broken into separate words at blanks, tabs and newlines, and null words are discarded. The output is variable and command substituted and put in place of the original string.

Command substitutions inside double
quotes (‘”’) retain blanks and tabs; only newlines force new words. The single
final newline does not force a new word in any case. It is thus possible for a
command substitution to yield only part of a word, even if the command outputs
a complete line.

By default, the shell since version 6.12 replaces all newline and carriage
return characters in the command by spaces. If this is switched off by
unsetting csubstnonl, newlines separate commands as usual.

If a word contains any of the characters ‘*’, ‘?’, ‘[’ or ‘{’ or begins with
the character ‘~’ it is a candidate for filename substitution, also known as
‘‘globbing’’. This word is then regarded as a pattern (‘‘glob-pattern’’), and
replaced with an alphabetically sorted list of file names which match the
pattern.

If a word contains any of the characters ‘*’, ‘?’, ‘[’ or ‘{’ or begins with the character ‘~’ it is a candidate for filename substitution, also known as ‘‘globbing’’. This word is then regarded as a pattern (‘‘glob-pattern’’), and replaced with an alphabetically sorted list of file names which match the pattern.

In matching filenames, the character ‘.’ at the beginning of a filename or
immediately following a ‘/’, as well as the character ‘/’ must be matched
explicitly. The character ‘*’ matches any string of characters, including the
null string. The character ‘?’ matches any single character. The sequence
‘[…]’ matches any one of the characters enclosed. Within ‘[…]’, a pair of
characters separated by ‘-’ matches any character lexically between the two.

(+) Some glob-patterns can be negated:
The sequence ‘[^…]’ matches any single character specified by the
characters and/or ranges of characters in the braces.

An entire glob-pattern can also be negated with ‘^’:

TagDescription

> echo *

bang crash crunch ouch

> echo ^cr*

bang ouch

Glob-patterns which do not use ‘?’, ‘*’, or ‘[]’ or which use ‘{}’ or ‘~’
(below) are not negated correctly.

Glob-patterns which do not use ‘?’, ‘*’, or ‘[]’ or which use ‘{}’ or ‘~’ (below) are not negated correctly.

The metanotation ‘a{b,c,d}e’ is a shorthand for ‘abe ace ade’.
Left-to-right order is preserved: ‘/usr/source/s1/{oldls,ls}.c’ expands
to ‘/usr/source/s1/oldls.c /usr/source/s1/ls.c’. The results of matches are
sorted separately at a low level to preserve this order:
‘../{memo,*box}’ might expand to ‘../memo ../box ../mbox’.
(Note that ‘memo’ was not sorted with the results of matching ‘*box’.)
It is not an error when this construct expands to files which do not exist,
but it is possible to get an error from a command to which the expanded list
is passed.
This construct may be nested.
As a special case the words ‘{’, ‘}’ and ‘{}’ are passed undisturbed.

The character ‘~’ at the beginning of a filename refers to home directories.
Standing alone, i.e., ‘~’, it expands to the invoker’s home directory as
reflected in the value of the home shell variable. When followed by a
name consisting of letters, digits and ‘-’ characters the shell searches for a
user with that name and substitutes their home directory; thus ‘~ken’ might
expand to ‘/usr/ken’ and ‘~ken/chmach’ to ‘/usr/ken/chmach’. If the character
‘~’ is followed by a character other than a letter or ‘/’ or appears elsewhere
than at the beginning of a word, it is left undisturbed.
A command like ‘setenv MANPATH /usr/man:/usr/local/man:~/lib/man’ does not,
therefore, do home directory substitution as one might hope.

It is an error for a glob-pattern containing ‘*’, ‘?’, ‘[’ or ‘~’, with or
without ‘^’, not to match any files. However, only one pattern in a list of
glob-patterns must match a file (so that, e.g., ‘rm *.a *.c *.o’ would fail
only if there were no files in the current directory ending in ‘.a’, ‘.c’, or
‘.o’), and if the nonomatch shell variable is set a pattern (or list
of patterns) which matches nothing is left unchanged rather than causing
an error.

The noglob shell variable can be set to prevent filename substitution,
and the editor command, normally bound to ‘^X-*’, can be
used to interactively expand individual filename substitutions.

The directory stack is a list of directories, numbered from zero, used by the
, and builtin commands (q.v.).
can print, store in a file, restore and clear the directory stack
at any time, and the savedirs and dirsfile shell variables can be set to
store the directory stack automatically on logout and restore it on login.
The dirstack shell variable can be examined to see the directory stack and
set to put arbitrary directories into the directory stack.

The directory stack is a list of directories, numbered from zero, used by theandbuiltin commands (q.v.).can print, store in a file, restore and clear the directory stack at any time, and theandshell variables can be set to store the directory stack automatically on logout and restore it on login. Theshell variable can be examined to see the directory stack and set to put arbitrary directories into the directory stack.

The character ‘=’ followed by one or more digits expands to an entry in
the directory stack. The special case ‘=-’ expands to the last directory in
the stack. For example,

TagDescription

> dirs -v

0 /usr/bin

1 /usr/spool/uucp

2 /usr/accts/sys

> echo =1

/usr/spool/uucp

> echo =0/calendar

/usr/bin/calendar

> echo =-

/usr/accts/sys

The noglob and nonomatch shell variables and the
editor command apply to directory stack as well as filename substitutions.

There are several more transformations involving filenames, not strictly
related to the above but mentioned here for completeness.
filename may be expanded to a full path when the
symlinks variable (q.v.) is set to ‘expand’.
Quoting prevents this expansion, and
the editor command does it on demand.
The editor command expands commands in PATH into
full paths on demand.
Finally, and interpret ‘-’ as the old working directory
(equivalent to the shell variable owd).
This is not a substitution at all, but an abbreviation recognized by only
those commands. Nonetheless, it too can be prevented by quoting.

The next three sections describe how the shell executes commands and
deals with their input and output.

A simple command is a sequence of words, the first of which specifies the
command to be executed. A series of simple commands joined by ‘|’ characters
forms a pipeline. The output of each command in a pipeline is connected to the
input of the next.

Theandshell variables and theeditor command apply to directory stack as well as filename substitutions.There are several more transformations involving filenames, not strictly related to the above but mentioned here for completeness.filename may be expanded to a full path when thevariable (q.v.) is set to ‘expand’. Quoting prevents this expansion, and theeditor command does it on demand. Theeditor command expands commands in PATH into full paths on demand. Finally,andinterpret ‘-’ as the old working directory (equivalent to the shell variable). This is not a substitution at all, but an abbreviation recognized by only those commands. Nonetheless, it too can be prevented by quoting.The next three sections describe how the shell executes commands and deals with their input and output.A simple command is a sequence of words, the first of which specifies the command to be executed. A series of simple commands joined by ‘|’ characters forms a pipeline. The output of each command in a pipeline is connected to the input of the next.

Simple commands and pipelines may be joined into sequences with ‘;’, and will
be executed sequentially. Commands and pipelines can also be joined into
sequences with ‘||’ or ‘&&’, indicating, as in the C language, that the second
is to be executed only if the first fails or succeeds respectively.

A simple command, pipeline or sequence may be placed in parentheses, ‘()’,
to form a simple command, which may in turn be a component of a pipeline or
sequence. A command, pipeline or sequence can be executed
without waiting for it to terminate by following it with an ‘&’.

Builtin commands are executed within the shell. If any component of a
pipeline except the last is a builtin command, the pipeline is executed
in a subshell.

Builtin commands are executed within the shell. If any component of a pipeline except the last is a builtin command, the pipeline is executed in a subshell.

Parenthesized commands are always executed in a subshell.

TagDescription

(cd; pwd); pwd

thus prints the home directory, leaving you where you were
(printing this after the home directory), while

TagDescription

cd; pwd

leaves you in the home directory. Parenthesized commands are most often
used to prevent from affecting the current shell.

thus prints thedirectory, leaving you where you were (printing this after the home directory), whileleaves you in thedirectory. Parenthesized commands are most often used to preventfrom affecting the current shell.

When a command to be executed is found not to be a builtin command the shell
attempts to execute the command via (2). Each word in the variable
path names a directory in which the shell will look for the
command. If it is given neither a -c nor a -t option, the shell
hashes the names in these directories into an internal table so that it will
try an (2) in only a directory where there is a possibility that the
command resides there. This greatly speeds command location when a large
number of directories are present in the search path. If this mechanism has
been turned off (via ), if the shell was given a -c or
-t argument or in any case for each directory component of path
which does not begin with a ‘/’, the shell concatenates the current working
directory with the given command name to form a path name of a file which it
then attempts to execute.

If the file has execute permissions but is not an executable to the system
(i.e., it is neither an executable binary nor a script that specifies its
interpreter), then it is assumed to be a file containing shell commands and
a new shell is spawned to read it. The special alias may be set
to specify an interpreter other than the shell itself.

On systems which do not understand the ‘#!’ script interpreter convention
the shell may be compiled to emulate it; see the version shell
variable. If so, the shell checks the first line of the file to
see if it is of the form ‘#! …’. If it is,
the shell starts with the given s and feeds the
file to it on standard input.

The standard input and standard output of a command may be redirected with the
following syntax:

The standard input and standard output of a command may be redirected with the following syntax:

TagDescription

<
Open file (which is first variable, command and filename
expanded) as the standard input.

<<
Read the shell input up to a line which is identical to .
is not subjected to variable, filename or command substitution, and each input
line is compared to before any substitutions are done on this input
line. Unless a quoting ‘\’, ‘”’, ‘’ or ‘‘’ appears in variable and
command substitution is performed on the intervening lines, allowing ‘\’ to
quote ‘$’, ‘\’ and ‘‘’. Commands which are substituted have all blanks, tabs,
and newlines preserved, except for the final newline which is dropped. The
resultant text is placed in an anonymous temporary file which is given to the
command as standard input.

>

>&!
The file is used as standard output. If the file does not exist
then it is created; if the file exists, it is truncated, its previous contents
being lost.

If the shell variable noclobber is set, then the file must not exist or be a
character special file (e.g., a terminal or ‘/dev/null’) or an error results.
This helps prevent accidental destruction of files. In this case the ‘!’ forms
can be used to suppress this check.

The forms involving ‘&’ route the diagnostic output into the specified file as
well as the standard output. is expanded in the same way as ‘<’
input filenames are.

>>

>>&!
Like ‘>’, but appends output to the end of .
If the shell variable noclobber is set, then it is an error for
the file to exist, unless one of the ‘!’ forms is given.

A command receives the environment in which the shell was invoked as modified
by the input-output parameters and the presence of the command in a pipeline.
Thus, unlike some previous shells, commands run from a file of shell commands
have no access to the text of the commands by default; rather they receive the
original standard input of the shell. The ‘<<’ mechanism should be used to
present inline data. This permits shell command scripts to function as
components of pipelines and allows the shell to block read its input. Note
that the default standard input for a command run detached is
the empty file , but the original standard input of the shell.
If this is a terminal and if the process attempts to read from the terminal,
then the process will block and the user will be notified (see ).

A command receives the environment in which the shell was invoked as modified by the input-output parameters and the presence of the command in a pipeline. Thus, unlike some previous shells, commands run from a file of shell commands have no access to the text of the commands by default; rather they receive the original standard input of the shell. The ‘<

Diagnostic output may be directed through a pipe with the standard output.
Simply use the form ‘|&’ rather than just ‘|’.

The shell cannot presently redirect diagnostic output without also redirecting
standard output, but ‘( > ) >& ’
is often an acceptable workaround. Either or
may be ‘/dev/tty’ to send output to the terminal.

Having described how the shell accepts, parses and executes
command lines, we now turn to a variety of its useful features.

The shell contains a number of commands which can be used to regulate the
flow of control in command files (shell scripts) and (in limited but
useful ways) from terminal input. These commands all operate by forcing the
shell to reread or skip in its input and, due to the implementation,
restrict the placement of some of the commands.

Having described how the shell accepts, parses and executes command lines, we now turn to a variety of its useful features.The shell contains a number of commands which can be used to regulate the flow of control in command files (shell scripts) and (in limited but useful ways) from terminal input. These commands all operate by forcing the shell to reread or skip in its input and, due to the implementation, restrict the placement of some of the commands.

The , , and statements, as well as the
form of the statement, require that the major
keywords appear in a single simple command on an input line as shown below.

If the shell’s input is not seekable, the shell buffers up input whenever
a loop is being read and performs seeks in this internal buffer to
accomplish the rereading implied by the loop. (To the extent that this
allows, backward s will succeed on non-seekable inputs.)

The , and builtin commands
use expressions with a common syntax. The expressions can include any
of the operators described in the next three sections. Note that the
builtin command (q.v.) has its own separate syntax.

These operators are similar to those of C and have the same precedence.
They include

TagDescription

|| && | ^ & == != =~ !~ <= >=

< > << >> + – * / % ! ~ ( )

Here the precedence increases to the right, ‘==’ ‘!=’ ‘=~’ and ‘!~’, ‘<=’
‘>=’ ‘<’ and ‘>’, ‘<<’ and ‘>>’, ‘+’ and ‘-’, ‘*’ ‘/’ and ‘%’ being, in
groups, at the same level. When multiple operators which have same precedence
are used in one expression, calculation must be done from operator of right
side. The ‘==’ ‘!=’ ‘=~’ and ‘!~’ operators compare
their arguments as strings; all others operate on numbers. The operators
‘=~’ and ‘!~’ are like ‘!=’ and ‘==’ except that the right hand side is a
glob-pattern (see Filename substitution) against which the left hand
operand is matched. This reduces the need for use of the
builtin command in shell scripts when all that is really needed is
pattern matching.

Theandbuiltin commands use expressions with a common syntax. The expressions can include any of the operators described in the next three sections. Note that thebuiltin command (q.v.) has its own separate syntax.These operators are similar to those of C and have the same precedence. They includeHere the precedence increases to the right, ‘==’ ‘!=’ ‘=~’ and ‘!~’, ‘<=’ ‘>=’ ‘’, ‘<>’, ‘+’ and ‘-’, ‘*’ ‘/’ and ‘%’ being, in groups, at the same level. When multiple operators which have same precedence are used in one expression, calculation must be done from operator of right side. The ‘==’ ‘!=’ ‘=~’ and ‘!~’ operators compare their arguments as strings; all others operate on numbers. The operators ‘=~’ and ‘!~’ are like ‘!=’ and ‘==’ except that the right hand side is a glob-pattern (see) against which the left hand operand is matched. This reduces the need for use of thebuiltin command in shell scripts when all that is really needed is pattern matching.

Strings which begin with ‘0’ are considered octal numbers. Null or
missing arguments are considered ‘0’. The results of all expressions are
strings, which represent decimal numbers. It is important to note that
no two components of an expression can appear in the same word; except
when adjacent to components of expressions which are syntactically
significant to the parser (‘&’ ‘|’ ‘<’ ‘>’ ‘(’ ‘)’) they should be
surrounded by spaces.

Commands can be executed in expressions and their exit status
returned by enclosing them in braces (‘{}’). Remember that the braces should
be separated from the words of the command by spaces. Command executions
succeed, returning true, i.e., ‘1’, if the command exits with status 0,
otherwise they fail, returning false, i.e., ‘0’. If more detailed status
information is required then the command should be executed outside of an
expression and the status shell variable examined.

Some of these operators perform true/false tests on files and related
objects. They are of the form , where is one of

Commands can be executed in expressions and their exit status returned by enclosing them in braces (‘{}’). Remember that the braces should be separated from the words of the command by spaces. Command executions succeed, returning true, i.e., ‘1’, if the command exits with status 0, otherwise they fail, returning false, i.e., ‘0’. If more detailed status information is required then the command should be executed outside of an expression and theshell variable examined.Some of these operators perform true/false tests on files and related objects. They are of the form, whereis one of

TagDescription

r
Read access

w
Write access

x
Execute access

X
Executable in the path or shell builtin, e.g., ‘-X ls’ and ‘-X ls-F’ are
generally true, but ‘-X /bin/ls’ is not (+)

e
Existence

o
Ownership

z
Zero size

s
Non-zero size (+)

f
Plain file

d
Directory

l
Symbolic link (+) *

b
Block special file (+)

c
Character special file (+)

p
Named pipe (fifo) (+) *

S
Socket special file (+) *

u
Set-user-ID bit is set (+)

g
Set-group-ID bit is set (+)

k
Sticky bit is set (+)

t
(which must be a digit) is an open file descriptor
for a terminal device (+)

R
Has been migrated (convex only) (+)

L
Applies subsequent operators in a multiple-operator test to a symbolic link
rather than to the file to which the link points (+) *

is command and filename expanded and then tested to
see if it has the specified relationship to the real user. If
does not exist or is inaccessible or, for the operators indicated by ‘*’,
if the specified file type does not exist on the current system,
then all enquiries return false, i.e., ‘0’.

These operators may be combined for conciseness: ‘-’ is
equivalent to ‘- && -’. (+) For example, ‘-fx’ is true
(returns ‘1’) for plain executable files, but not for directories.

L may be used in a multiple-operator test to apply subsequent operators
to a symbolic link rather than to the file to which the link points.
For example, ‘-lLo’ is true for links owned by the invoking user.
Lr, Lw and Lx are always true for links and false for
non-links. L has a different meaning when it is the last operator
in a multiple-operator test; see below.

It is possible but not useful, and sometimes misleading, to combine operators
which expect to be a file with operators which do not,
(e.g., X and t). Following L with a non-file operator
can lead to particularly strange results.

Other operators return other information, i.e., not just ‘0’ or ‘1’. (+)
They have the same format as before; may be one of

TagDescription

A
Last file access time, as the number of seconds since the epoch

A:
Like A, but in timestamp format, e.g., ‘Fri May 14 16:36:10 1993’

M
Last file modification time

M:
Like M, but in timestamp format

C
Last inode modification time

C:
Like C, but in timestamp format

D
Device number

I
Inode number

F
Composite file identifier, in the form :
L
The name of the file pointed to by a symbolic link

N
Number of (hard) links

P
Permissions, in octal, without leading zero

P:
Like P, with leading zero

P
Equivalent to ‘-P & ’, e.g., ‘-P22 ’ returns
‘22’ if is writable by group and other, ‘20’ if by group only,
and ‘0’ if by neither

P:
Like P:, with leading zero

U
Numeric userid

U:
Username, or the numeric userid if the username is unknown

G
Numeric groupid

G:
Groupname, or the numeric groupid if the groupname is unknown

Z
Size, in bytes

Only one of these operators may appear in a multiple-operator test, and it
must be the last. Note that L has a different meaning at the end of and
elsewhere in a multiple-operator test. Because ‘0’ is a valid return value
for many of these operators, they do not return ‘0’ when they fail: most
return ‘-1’, and F returns ‘:’.

If the shell is compiled with POSIX defined (see the version shell
variable), the result of a file inquiry is based on the permission bits of
the file and not on the result of the (2) system call.
For example, if one tests a file with -w whose permissions would
ordinarily allow writing but which is on a file system mounted read-only,
the test will succeed in a POSIX shell but fail in a non-POSIX shell.

File inquiry operators can also be evaluated with the builtin
command (q.v.) (+).

The shell associates a with each pipeline. It keeps a table of
current jobs, printed by the command, and assigns them small integer
numbers. When a job is started asynchronously with ‘&’, the shell prints a
line which looks like

TagDescription

[1] 1234

indicating that the job which was started asynchronously was job number 1 and
had one (top-level) process, whose process id was 1234.

The shell associates awith each pipeline. It keeps a table of current jobs, printed by thecommand, and assigns them small integer numbers. When a job is started asynchronously with ‘&’, the shell prints a line which looks likeindicating that the job which was started asynchronously was job number 1 and had one (top-level) process, whose process id was 1234.

If you are running a job and wish to do something else you may hit the suspend
key (usually ‘^Z’),
which sends a STOP signal to the current job. The shell will then normally
indicate that the job has been ‘Suspended’ and print another prompt.
If the listjobs shell variable is set, all jobs will be listed
like the builtin command; if it is set to ‘long’ the listing will
be in long format, like ‘jobs -l’.
You can then manipulate the state of the suspended job.
You can put it in the
‘‘background’’ with the command or run some other commands and
eventually bring the job back into the ‘‘foreground’’ with .
(See also the editor command.)
A ‘^Z’ takes effect immediately and is like an interrupt
in that pending output and unread input are discarded when it is typed.
The builtin command causes the shell to wait for all background
jobs to complete.

The ‘^]’ key sends a delayed suspend signal, which does not generate a STOP
signal until a program attempts to (2) it, to the current job.
This can usefully be typed ahead when you have prepared some commands for a
job which you wish to stop after it has read them.
The ‘^Y’ key performs this function in (1); in ,
‘^Y’ is an editing command. (+)

A job being run in the background stops if it tries to read from the
terminal. Background jobs are normally allowed to produce output, but this can
be disabled by giving the command ‘stty tostop’. If you set this tty option,
then background jobs will stop when they try to produce output like they do
when they try to read input.

There are several ways to refer to jobs in the shell. The character ‘%’
introduces a job name. If you wish to refer to job number 1, you can name it
as ‘%1’. Just naming a job brings it to the foreground; thus ‘%1’ is a synonym
for ‘fg %1’, bringing job 1 back into the foreground. Similarly, saying ‘%1 &’
resumes job 1 in the background, just like ‘bg %1’. A job can also be named
by an unambiguous prefix of the string typed in to start it: ‘%ex’ would
normally restart a suspended (1) job, if there were only one suspended
job whose name began with the string ‘ex’. It is also possible to say
‘%?’ to specify a job whose text contains , if there
is only one such job.

The shell maintains a notion of the current and previous jobs. In output
pertaining to jobs, the current job is marked with a ‘+’ and the previous job
with a ‘-’. The abbreviations ‘%+’, ‘%’, and (by analogy with the syntax of
the mechanism) ‘%%’ all refer to the current job, and ‘%-’ refers
to the previous job.

The job control mechanism requires that the (1) option ‘new’ be set
on some systems. It is an artifact from a ‘new’ implementation of the tty
driver which allows generation of interrupt characters from the keyboard to
tell jobs to stop. See (1) and the builtin command for
details on setting options in the new tty driver.

The shell learns immediately whenever a process changes state. It normally
informs you whenever a job becomes blocked so that no further progress is
possible, but only right before it prints a prompt. This is done so that it
does not otherwise disturb your work. If, however, you set the shell variable
notify, the shell will notify you immediately of changes of status in
background jobs. There is also a shell command which marks a
single process so that its status changes will be immediately reported. By
default marks the current process; simply say ‘notify’ after
starting a background job to mark it.

The shell learns immediately whenever a process changes state. It normally informs you whenever a job becomes blocked so that no further progress is possible, but only right before it prints a prompt. This is done so that it does not otherwise disturb your work. If, however, you set the shell variable, the shell will notify you immediately of changes of status in background jobs. There is also a shell commandwhich marks a single process so that its status changes will be immediately reported. By defaultmarks the current process; simply say ‘notify’ after starting a background job to mark it.

When you try to leave the shell while jobs are stopped, you will be
warned that ‘You have stopped jobs.’ You may use the command to see
what they are. If you do this or immediately try to exit again, the shell will
not warn you a second time, and the suspended jobs will be terminated.

There are various ways to run commands and take other actions automatically
at various times in the ‘‘life cycle’’ of the shell. They are summarized here,
and described in detail under the appropriate Builtin commands,
Special shell variables and Special aliases.

There are various ways to run commands and take other actions automatically at various times in the ‘‘life cycle’’ of the shell. They are summarized here, and described in detail under the appropriateand

The builtin command puts commands in a scheduled-event list,
to be executed by the shell at a given time.

The , , , , ,
and
Special aliases can be set, respectively, to execute commands when the shell wants
to ring the bell, when the working directory changes, every tperiod
minutes, before each prompt, before each command gets executed, after each
command gets executed, and when a job is started or is brought into the
foreground.

The autologout shell variable can be set to log out or lock the shell
after a given number of minutes of inactivity.

The mail shell variable can be set to check for new mail periodically.

The printexitvalue shell variable can be set to print the exit status
of commands which exit with a status other than zero.

The rmstar shell variable can be set to ask the user, when ‘rm *’ is
typed, if that is really what was meant.

The time shell variable can be set to execute the builtin
command after the completion of any process that takes more than a given
number of CPU seconds.

The watch and who shell variables can be set to report when
selected users log in or out, and the builtin command reports
on those users at any time.

The shell is eight bit clean
(if so compiled; see the version shell variable)
and thus supports character sets needing this capability.
NLS support differs depending on whether or not
the shell was compiled to use the system’s NLS (again, see version).
In either case, 7-bit ASCII is the default character code
(e.g., the classification of which characters are printable) and sorting,
and changing the LANG or LC_CTYPE environment variables
causes a check for possible changes in these respects.

The shell is eight bit clean (if so compiled; see theshell variable) and thus supports character sets needing this capability. NLS support differs depending on whether or not the shell was compiled to use the system’s NLS (again, see). In either case, 7-bit ASCII is the default character code (e.g., the classification of which characters are printable) and sorting, and changing theorenvironment variables causes a check for possible changes in these respects.

When using the system’s NLS, the (3) function is called
to determine appropriate character code/classification and sorting
(e.g., a ’en_CA.UTF-8’ would yield “UTF-8” as a character code).
This function typically examines the LANG and LC_CTYPE
environment variables; refer to the system documentation for further details.
When not using the system’s NLS, the shell simulates it by assuming that the
ISO 8859-1 character set is used
whenever either of the LANG and LC_CTYPE variables are set, regardless of
their values. Sorting is not affected for the simulated NLS.

In addition, with both real and simulated NLS, all printable
characters in the range \200-\377, i.e., those that have
M- bindings, are automatically rebound to .
The corresponding binding for the escape- sequence, if any, is
left alone.
These characters are not rebound if the NOREBIND environment variable
is set. This may be useful for the simulated NLS or a primitive real NLS
which assumes full ISO 8859-1. Otherwise, all M- bindings in the
range \240-\377 are effectively undone.
Explicitly rebinding the relevant keys with
is of course still possible.

Unknown characters (i.e., those that are neither printable nor control
characters) are printed in the format \nnn.
If the tty is not in 8 bit mode, other 8 bit characters are printed by
converting them to ASCII and using standout mode. The shell
never changes the 7/8 bit mode of the tty and tracks user-initiated
changes of 7/8 bit mode. NLS users (or, for that matter, those who want to
use a meta key) may need to explicitly set
the tty in 8 bit mode through the appropriate (1)
command in, e.g., the file.

A number of new builtin commands are provided to support features in
particular operating systems. All are described in detail in the
Builtin commands section.

A number of new builtin commands are provided to support features in particular operating systems. All are described in detail in thesection.

On systems that support TCF (aix-ibm370, aix-ps2),
and get and set the system execution path,
and get and set the experimental version prefix
and migrates processes between sites. The builtin
prints the site on which each job is executing.

Under BS2000, executes commands of the underlying BS2000/OSD
operating system.

Under Domain/OS, adds shared libraries to the current environment,
changes the rootnode and changes the systype.

Under Mach, is equivalent to Mach’s (1).

Under Masscomp/RTU and Harris CX/UX, sets the universe.

Under Harris CX/UX, or runs a command under the specified
universe.

Under Convex/OS, prints or sets the universe.

The VENDOR, OSTYPE and MACHTYPE environment variables
indicate respectively the vendor, operating system and machine type
(microprocessor class or machine model) of the
system on which the shell thinks it is running.
These are particularly useful when sharing one’s home directory between several
types of machines; one can, for example,

TagDescription

set path = (~/bin.$MACHTYPE /usr/ucb /bin /usr/bin .)

in one’s and put executables compiled for each machine in the
appropriate directory.

in one’sand put executables compiled for each machine in the appropriate directory.

The version shell
variable indicates what options were chosen when the shell was compiled.

Note also the builtin, the afsuser and
echo_style shell variables and the system-dependent locations of
the shell’s input files (see FILES).

Login shells ignore interrupts when reading the file .
The shell ignores quit signals unless started with -q.
Login shells catch the terminate signal, but non-login shells inherit the
terminate behavior from their parents.
Other signals have the values which the shell inherited from its parent.

Login shells ignore interrupts when reading the file. The shell ignores quit signals unless started with. Login shells catch the terminate signal, but non-login shells inherit the terminate behavior from their parents. Other signals have the values which the shell inherited from its parent.

In shell scripts, the shell’s handling of interrupt and terminate signals
can be controlled with , and its handling of hangups can be
controlled with and .

The shell exits on a hangup (see also the logout shell variable). By
default, the shell’s children do too, but the shell does not send them a
hangup when it exits. arranges for the shell to send a hangup to
a child when it exits, and sets a child to ignore hangups.

The shell uses three different sets of terminal (‘‘tty’’) modes:
‘edit’, used when editing, ‘quote’, used when quoting literal characters,
and ‘execute’, used when executing commands.
The shell holds some settings in each mode constant, so commands which leave
the tty in a confused state do not interfere with the shell.
The shell also matches changes in the speed and padding of the tty.
The list of tty modes that are kept constant
can be examined and modified with the builtin.
Note that although the editor uses CBREAK mode (or its equivalent),
it takes typed-ahead characters anyway.

The shell uses three different sets of terminal (‘‘tty’’) modes: ‘edit’, used when editing, ‘quote’, used when quoting literal characters, and ‘execute’, used when executing commands. The shell holds some settings in each mode constant, so commands which leave the tty in a confused state do not interfere with the shell. The shell also matches changes in the speed and padding of the tty. The list of tty modes that are kept constant can be examined and modified with thebuiltin. Note that although the editor uses CBREAK mode (or its equivalent), it takes typed-ahead characters anyway.

The , and commands can be used to
manipulate and debug terminal capabilities from the command line.

On systems that support SIGWINCH or SIGWINDOW, the shell
adapts to window resizing automatically and adjusts the environment
variables LINES and COLUMNS if set. If the environment
variable TERMCAP contains li# and co# fields, the shell adjusts
them to reflect the new window size.

REFERENCE

The next sections of this manual describe all of the available
Builtin commands, Special aliases and
Special shell variables.

TagDescription

%
A synonym for the builtin command.

%&
A synonym for the builtin command.

:
Does nothing, successfully.

@
@ =
@ [] =
@ ++|
@ []++|  
The first form prints the values of all shell variables.

The second form assigns the value of to .
The third form assigns the value of to the ’th
component of ; both and its ’th component
must already exist.

may contain the operators ‘*’, ‘+’, etc., as in C.
If contains ‘<’, ‘>’, ‘&’ or ‘’ then at least that part of
must be placed within ‘()’.
Note that the syntax of has nothing to do with that described
under Expressions.

The fourth and fifth forms increment (‘++’) or decrement (‘–’)
or its ’th component.

The space between ‘@’ and is required. The spaces between
and ‘=’ and between ‘=’ and are optional. Components of
must be separated by spaces.

alias [[]]  
Without arguments, prints all aliases.
With , prints the alias for name.
With and , assigns
as the alias of .
is command and filename substituted.
may not be ‘alias’ or ‘unalias’.
See also the builtin command.

alloc
Shows the amount of dynamic memory acquired, broken down into used and free
memory. With an argument shows the number of free and used blocks in each size
category. The categories start at size 8 and double at each step. This
command’s output may vary across system types, because systems other than the VAX
may use a different memory allocator.

bg [% …]  
Puts the specified jobs (or, without arguments, the current job)
into the background, continuing each if it is stopped.
may be a number, a string, ‘’, ‘%’, ‘+’ or ‘-’ as described
under Jobs.

bindkey [-l|-d|-e|-v|-u] (+)
bindkey [-a] [-b] [-k] [-r] [] (+)

bindkey [-a] [-b] [-k] [-c|-s] [] (+)
 
Without options, the first form lists all bound keys and the editor command to which each is bound,
the second form lists the editor command to which is bound and
the third form binds the editor command to .
Options include:

TagDescription

-l
Lists all editor commands and a short description of each.

-d
Binds all keys to the standard bindings for the default editor.

-e
Binds all keys to the standard GNU Emacs-like bindings.

-v
Binds all keys to the standard (1)-like bindings.

-a
Lists or changes key-bindings in the alternative key map.
This is the key map used in command mode.

-b
is interpreted as
a control character written ^ (e.g., ‘^A’) or
C- (e.g., ‘C-A’),
a meta character written M- (e.g., ‘M-A’),
a function key written F- (e.g., ‘F-string’),
or an extended prefix key written X- (e.g., ‘X-A’).

-k
is interpreted as a symbolic arrow key name, which may be one of
‘down’, ‘up’, ‘left’ or ‘right’.

-r
Removes ’s binding.
Be careful: ‘bindkey -r’ does bind to
(q.v.), it unbinds completely.

-c
is interpreted as a builtin or external command instead of an
editor command.

-s
is taken as a literal string and treated as terminal input
when is typed. Bound keys in are themselves
reinterpreted, and this continues for ten levels of interpretation.


Forces a break from option processing, so the next word is taken as
even if it begins with ’-’.

-u (or any invalid option)  
Prints a usage message.

may be a single character or a string.
If a command is bound to a string, the first character of the string is bound to
and the entire string is bound to the command.

Control characters in can be literal (they can be typed by preceding
them with the editor command , normally bound to ‘^V’) or
written caret-character style, e.g., ‘^A’. Delete is written ‘^?’
(caret-question mark). and can contain backslashed
escape sequences (in the style of System V (1)) as follows:

TagDescription
 

TagDescription

\a
Bell

\b
Backspace

\e
Escape

\f
Form feed

\n
Newline

\r
Carriage return

\t
Horizontal tab

\v
Vertical tab

\
The ASCII character corresponding to the octal number

‘\’ nullifies the special meaning of the following character, if it has
any, notably ‘#146; and ‘^’.

bs2cmd (+)  
Passes to the BS2000 command interpreter for
execution. Only non-interactive commands can be executed, and it is
not possible to execute any command that would overlay the image
of the current process, like /EXECUTE or /CALL-PROCEDURE. (BS2000 only)

break
Causes execution to resume after the of the nearest
enclosing or . The remaining commands on the
current line are executed. Multi-level breaks are thus
possible by writing them all on one line.

breaksw
Causes a break from a , resuming after the .

builtins (+)  
Prints the names of all builtin commands.

bye (+)
A synonym for the builtin command.
Available only if the shell was so compiled;
see the version shell variable.

case :  
A label in a statement as discussed below.

cd [-p] [-l] [-n|-v] []  
If a directory is given, changes the shell’s working directory
to . If not, changes to home.
If is ‘-’ it is interpreted as the previous working directory
(see Other substitutions). (+)
If is not a subdirectory of the current directory
(and does not begin with ‘/’, ‘./’ or ‘../’), each component of the variable
cdpath is checked to see if it has a subdirectory . Finally, if
all else fails but is a shell variable whose value
begins with ‘/’, then this is tried to see if it is a directory.

With -p, prints the final directory stack, just like .
The -l, -n and -v flags have the same effect on
as on , and they imply -p. (+)

See also the implicitcd shell variable.

chdir
A synonym for the builtin command.

complete [ [//[:]/[[]/] …]] (+)  
Without arguments, lists all completions.
With , lists completions for .
With and etc., defines completions.

may be a full command name or a glob-pattern
(see Filename substitution). It can begin with ‘-’ to indicate that
completion should be used only when is ambiguous.

specifies which word relative to the current word
is to be completed, and may be one of the following:

TagDescription
 

TagDescription

c
Current-word completion.
is a glob-pattern which must match the beginning of the current word on
the command line. is ignored when completing the current word.

C
Like c, but includes when completing the current word.

n
Next-word completion.
is a glob-pattern which must match the beginning of the previous word on
the command line.

N
Like n, but must match the beginning of the word two before the current word.

p
Position-dependent completion.
is a numeric range, with the same syntax used to index shell
variables, which must include the current word.

, the list of possible completions, may be one of the following:

TagDescription
 

TagDescription

a
Aliases

b
Bindings (editor commands)

c
Commands (builtin or external commands)

C
External commands which begin with the supplied path prefix

d
Directories

D
Directories which begin with the supplied path prefix

e
Environment variables

f
Filenames

F
Filenames which begin with the supplied path prefix

g
Groupnames

j
Jobs

l
Limits

n
Nothing

s
Shell variables

S
Signals

t
Plain (‘‘text’’) files

T
Plain (‘‘text’’) files which begin with the supplied path prefix

v
Any variables

u
Usernames

x
Like n, but prints when is used.

X
Completions

$

Words from the variable

(…)

Words from the given list

‘…‘

Words from the output of command

is an optional glob-pattern.
If given, words from only that match are considered
and the fignore shell variable is ignored.
The last three types of completion may not have a
pattern, and x uses as an explanatory message when
the editor command is used.

is a single character to be appended to a successful
completion. If null, no character is appended. If omitted (in which
case the fourth delimiter can also be omitted), a slash is appended to
directories and a space to other words.

Now for some examples. Some commands take only directories as arguments,
so there’s no point completing plain files.

TagDescription

> complete cd ’p/1/d/’

completes only the first word following ‘cd’ (‘p/1’) with a directory.
p-type completion can also be used to narrow down command completion:

TagDescription

> co[^D]

complete compress

> complete -co* ’p/0/(compress)/’

> co[^D]

> compress

This completion completes commands (words in position 0, ‘p/0’)
which begin with ‘co’ (thus matching ‘co*’) to ‘compress’ (the only
word in the list).
The leading ‘-’ indicates that this completion is to be used with only
ambiguous commands.

TagDescription

> complete find ’n/-user/u/’

is an example of n-type completion. Any word following ‘find’ and
immediately following ‘-user’ is completed from the list of users.

TagDescription

> complete cc ’c/-I/d/’

demonstrates c-type completion. Any word following ‘cc’ and beginning
with ‘-I’ is completed as a directory. ‘-I’ is not taken as part of the
directory because we used lowercase c.

Different s are useful with different commands.

TagDescription

> complete alias ’p/1/a/’

> complete man ’p/*/c/’

> complete set ’p/1/s/’

> complete true ’p/1/x:Truth has no options./’

These complete words following ‘alias’ with aliases, ‘man’ with commands,
and ‘set’ with shell variables.
‘true’ doesn’t have any options, so x does nothing when completion
is attempted and prints ‘Truth has no options.’ when completion choices are listed.

Note that the example, and several other examples below, could
just as well have used ’c/*’ or ’n/*’ as ’p/*’.

Words can be completed from a variable evaluated at completion time,

TagDescription

> complete ftp ’p/1/$hostnames/’

> set hostnames = (rtfm.mit.edu tesla.ee.cornell.edu)

> ftp [^D]

rtfm.mit.edu tesla.ee.cornell.edu

> ftp [^C]

> set hostnames = (rtfm.mit.edu tesla.ee.cornell.edu uunet.uu.net)

> ftp [^D]

rtfm.mit.edu tesla.ee.cornell.edu uunet.uu.net

or from a command run at completion time:

TagDescription

> complete kill ’p/*/‘ps | awk \{print\ \$1\}‘/’

> kill -9 [^D]

23113 23377 23380 23406 23429 23529 23530 PID

Note that the command does not itself quote its arguments,
so the braces, space and ‘$’ in ‘{print $1}’ must be quoted explicitly.

One command can have multiple completions:

TagDescription

> complete dbx ’p/2/(core)/’ ’p/*/c/’

completes the second argument to ‘dbx’ with the word ‘core’ and all other
arguments with commands. Note that the positional completion is specified
before the next-word completion.
Because completions are evaluated from left to right, if
the next-word completion were specified first it would always match
and the positional completion would never be executed. This is a
common mistake when defining a completion.

The pattern is useful when a command takes files with only
particular forms as arguments. For example,

TagDescription

> complete cc ’p/*/f:*.[cao]/’

completes ‘cc’ arguments to files ending in only ‘.c’, ‘.a’, or ‘.o’.
can also exclude files, using negation of a glob-pattern as
described under Filename substitution. One might use

TagDescription

> complete rm ’p/*/f:^*.{c,h,cc,C,tex,1,man,l,y}/’

to exclude precious source code from ‘rm’ completion. Of course, one
could still type excluded names manually or override the completion
mechanism using the or
editor commands (q.v.).

The ‘C’, ‘D’, ‘F’ and ‘T’ s are like ‘c’, ‘d’, ‘f’ and ‘t’
respectively, but they use the argument in a different way: to
restrict completion to files beginning with a particular path prefix. For
example, the Elm mail program uses ‘=’ as an abbreviation for one’s mail
directory. One might use

TagDescription

> complete elm c@=@F:$HOME/Mail/@

to complete ‘elm -f =’ as if it were ‘elm -f ~/Mail/’. Note that we used ‘@’
instead of ‘/’ to avoid confusion with the argument, and we used
‘$HOME’ instead of ‘~’ because home directory substitution works at only the
beginning of a word.

is used to add a nonstandard suffix
(not space or ‘/’ for directories) to completed words.

TagDescription

> complete finger ’c/*@/$hostnames/’ ’p/1/u/@’

completes arguments to ‘finger’ from the list of users, appends an ‘@’,
and then completes after the ‘@’ from the ‘hostnames’ variable. Note
again the order in which the completions are specified.

Finally, here’s a complex example for inspiration:

TagDescription

> complete find \

’n/-name/f/’ ’n/-newer/f/’ ’n/-{,n}cpio/f/’ \

‘n/-exec/c/’ ’n/-ok/c/’ ’n/-user/u/’ \

’n/-group/g/’ ’n/-fstype/(nfs 4.2)/’ \

’n/-type/(b c d f l p s)/’ \

‘c/-/(name newer cpio ncpio exec ok user \

group fstype type atime ctime depth inum \

ls mtime nogroup nouser perm print prune \

size xdev)/’ \

’p/*/d/’

This completes words following ‘-name’, ‘-newer’, ‘-cpio’ or ‘ncpio’
(note the pattern which matches both) to files,
words following ‘-exec’ or ‘-ok’ to commands, words following ‘user’
and ‘group’ to users and groups respectively
and words following ‘-fstype’ or ‘-type’ to members of the
given lists. It also completes the switches themselves from the given list
(note the use of c-type completion)
and completes anything not otherwise completed to a directory. Whew.

Remember that programmed completions are ignored if the word being completed
is a tilde substitution (beginning with ‘~’) or a variable (beginning with ‘$’).
is an experimental feature, and the syntax may change
in future versions of the shell.
See also the builtin command.

continue
Continues execution of the nearest enclosing or .
The rest of the commands on the current line are executed.

default:
Labels the default case in a statement.
It should come after all labels.

dirs [-l] [-n|-v]
dirs -S|-L [] (+)

dirs -c (+)
The first form prints the directory stack. The top of the stack is at the
left and the first directory in the stack is the current directory.
With -l, ‘~’ or ‘~’ in the output is expanded explicitly
to home or the pathname of the home directory for user . (+)
With -n, entries are wrapped before they reach the edge of the screen. (+)
With -v, entries are printed one per line, preceded by their stack positions. (+)
If more than one of -n or -v is given, -v takes precedence.
-p is accepted but does nothing.

With -S, the second form saves the directory stack to
as a series of and commands.
With -L, the shell sources , which is presumably
a directory stack file saved by the -S option or the savedirs
mechanism.
In either case, dirsfile is used if is not given and
is used if dirsfile is unset.

Note that login shells do the equivalent of ‘dirs -L’ on startup
and, if savedirs is set, ‘dirs -S’ before exiting.
Because only is normally sourced before ,
dirsfile should be set in rather than .

The last form clears the directory stack.

echo [-n] …  
Writes each to the shell’s standard
output, separated by spaces and terminated with a newline.
The echo_style shell variable may be set to emulate (or not) the flags and escape
sequences of the BSD and/or System V versions of ; see (1).

echotc [-sv] … (+)  
Exercises the terminal capabilities (see (5)) in .
For example, ’echotc home’ sends the cursor to the home position,
’echotc cm 3 10’ sends it to column 3 and row 10, and
’echotc ts 0; echo “This is a test.”; echotc fs’ prints “This is a test.”
in the status line.

If is ’baud’, ’cols’, ’lines’, ’meta’ or ’tabs’, prints the
value of that capability (“yes” or “no” indicating that the terminal does
or does not have that capability). One might use this to make the output
from a shell script less verbose on slow terminals, or limit command
output to the number of lines on the screen:

TagDescription

> set history=‘echotc lines‘

> @ history–

Termcap strings may contain wildcards which will not echo correctly.
One should use double quotes when setting a shell variable to a terminal
capability string, as in the following example that places the date in
the status line:

TagDescription

> set tosl=”‘echotc ts 0‘”

> set frsl=”‘echotc fs‘”

> echo -n “$tosl”;date; echo -n “$frsl”

With -s, nonexistent capabilities return the empty string rather
than causing an error.
With -v, messages are verbose.

else
end
endif
endsw
See the description of the , , , and
statements below.

eval …  
Treats the arguments as input to the
shell and executes the resulting command(s) in the context
of the current shell. This is usually used to execute commands
generated as the result of command or variable substitution,
because parsing occurs before these substitutions.
See (1) for a sample use of .

exec  
Executes the specified command in place of the current shell.

exit []  
The shell exits either with the value of the specified
(an expression, as described under Expressions)
or, without , with the value of the status variable.

fg [% …]  
Brings the specified jobs (or, without arguments, the current job)
into the foreground, continuing each if it is stopped.
may be a number, a string, ‘’, ‘%’, ‘+’ or ‘-’ as described
under Jobs.
See also the editor command.

filetest – … (+)  
Applies (which is a file inquiry operator as described under
File inquiry operators) to each and returns the results as a
space-separated list.

foreach ()

end
Successively sets the variable to each member of
and executes the sequence of commands between this command
and the matching . (Both and
must appear alone on separate lines.) The builtin command
may be used to continue the loop prematurely and
the builtin command to terminate it prematurely.
When this command is read from the terminal, the loop is read once
prompting with ‘foreach? ’ (or prompt2) before any statements in
the loop are executed. If you make a mistake typing in a
loop at the terminal you can rub it out.

getspath (+)  
Prints the system execution path. (TCF only)

getxvers (+)  
Prints the experimental version prefix. (TCF only)

glob  
Like , but no ‘#146; escapes are recognized and words are
delimited by null characters in the output. Useful for
programs which wish to use the shell to filename expand a list of words.

goto  
is filename and command-substituted to
yield a string of the form ‘label’. The shell rewinds its
input as much as possible, searches for a line of the
form ‘label:’, possibly preceded by blanks or tabs, and
continues execution after that line.

hashstat
Prints a statistics line indicating how effective the
internal hash table has been at locating commands (and avoiding
’s). An is attempted for each component of the
path where the hash function indicates a possible hit, and
in each component which does not begin with a ‘/’.

On machines without (2), prints only the number and size of
hash buckets.

history [-hTr] []
history -S|-L|-M [] (+)

history -c (+)  
The first form prints the history event list.
If is given only the most recent events are printed or saved.
With -h, the history list is printed without leading numbers. If
-T is specified, timestamps are printed also in comment form.
(This can be used to
produce files suitable for loading with ’history -L’ or ’source -h’.)
With -r, the order of printing is most recent
first rather than oldest first.

With -S, the second form saves the history list to .
If the first word of the savehist shell variable is set to a
number, at most that many lines are saved. If the second word of
savehist is set to ‘merge’, the history list is merged with the
existing history file instead of replacing it (if there is one) and
sorted by time stamp. (+) Merging is intended for an environment like
the X Window System
with several shells in simultaneous use. Currently it succeeds
only when the shells quit nicely one after another.

With -L, the shell appends , which is presumably a
history list saved by the -S option or the savehist mechanism,
to the history list.
-M is like -L, but the contents of are merged
into the history list and sorted by timestamp.
In either case, histfile is used if is not given and
is used if histfile is unset.
‘history -L’ is exactly like ’source -h’ except that it does not require a
filename.

Note that login shells do the equivalent of ‘history -L’ on startup
and, if savehist is set, ‘history -S’ before exiting.
Because only is normally sourced before ,
histfile should be set in rather than .

If histlit is set, the first and second forms print and save the literal
(unexpanded) form of the history list.

The last form clears the history list.

hup [] (+)  
With , runs such that it will exit on a hangup
signal and arranges for the shell to send it a hangup signal when the shell
exits.
Note that commands may set their own response to hangups, overriding .
Without an argument (allowed in only a shell script), causes the shell to
exit on a hangup for the remainder of the script.
See also Signal handling and the builtin command.

if ()  
If (an expression, as described under Expressions)
evaluates true, then is executed.
Variable substitution on happens early, at the same time it
does for the rest of the command.
must be a simple command, not an alias, a pipeline, a command list
or a parenthesized command list, but it may have arguments.
Input/output redirection occurs even if is
false and is thus executed; this is a bug.

if () then


else if () then


else

endif
If the specified is true then the commands to the
first are executed; otherwise if is true then
the commands to the second are executed, etc. Any
number of pairs are possible; only one is
needed. The part is likewise optional. (The words
and must appear at the beginning of input lines;
the must appear alone on its input line or after an
.)

inlib … (+)  
Adds each to the current environment. There is no way
to remove a shared library. (Domain/OS only)

jobs [-l]
Lists the active jobs. With -l, lists process
IDs in addition to the normal information. On TCF systems, prints
the site on which each job is executing.

kill [-s ] %| …

kill -l  
The first and second forms sends the specified (or, if none
is given, the TERM (terminate) signal) to the specified jobs or processes.
may be a number, a string, ‘’, ‘%’, ‘+’ or ‘-’ as described
under Jobs.
Signals are either given by number or by name (as given in
, stripped of the prefix ‘SIG’).
There is no default ; saying just ‘kill’ does not send a signal
to the current job. If the signal being sent is TERM (terminate)
or HUP (hangup), then the job or process is sent a
CONT (continue) signal as well.
The third form lists the signal names.

limit [-h] [ []]  
Limits the consumption by the current process and each
process it creates to not individually exceed on
the specified . If no is given, then
the current limit is printed; if no is given, then
all limitations are given. If the -h flag is given, the
hard limits are used instead of the current limits. The
hard limits impose a ceiling on the values of the current
limits. Only the super-user may raise the hard limits, but
a user may lower or raise the current limits within the legal range.

Controllable resources currently include (if supported by the OS):

TagDescription

 
the maximum number of cpu-seconds to be used by each process

 
the largest single file which can be created

 
the maximum growth of the data+stack region via sbrk(2) beyond
the end of the program text

 
the maximum size of the automatically-extended stack region

 
the size of the largest core dump that will be created

 
the maximum amount of physical memory a process
may have allocated to it at a given time (this is not implemented in the 2.6 kernel. The value is meaningless
and changing this value will have no effect)

 
the maximum amount of memory a process
may allocate per system call

or
 
the maximum number of open files for this process

 
the maximum number of threads for this process

 
the maximum size which a process may lock into memory using mlock(2)

 
the maximum number of simultaneous processes for this user id

the maximum size of socket buffer usage for this user

may be given as a (floating point or
integer) number followed by a scale factor. For all limits
other than the default scale is ‘k’ or ‘kilobytes’
(1024 bytes); a scale factor of ‘m’ or ‘megabytes’ may also
be used. For the default scaling is ‘seconds’,
while ‘m’ for minutes or ‘h’ for hours, or a time of the
form ‘mm:ss’ giving minutes and seconds may be used.

For both names and scale factors, unambiguous
prefixes of the names suffice.

log (+)
Prints the watch shell variable and reports on each user indicated
in watch who is logged in, regardless of when they last logged in.
See also .

login
Terminates a login shell, replacing it with an instance of
This is one way to log off, included for
compatibility with (1).

logout
Terminates a login shell. Especially useful if ignoreeof is set.

ls-F [- …] [ …] (+)  
Lists files like ‘ls -F’, but much faster. It identifies each type of
special file in the listing with a special character:

TagDescription

/

Directory

*

Executable

#

Block device

%

Character device

|

Named pipe (systems with named pipes only)

=

Socket (systems with sockets only)

@

Symbolic link (systems with symbolic links only)

+

Hidden directory (AIX only) or context dependent (HP/UX only)

:

Network special (HP/UX only)

If the listlinks shell variable is set, symbolic links are identified
in more detail (on only systems that have them, of course):

@

Symbolic link to a non-directory

>

Symbolic link to a directory

&

Symbolic link to nowhere

listlinks also slows down and causes partitions holding
files pointed to by symbolic links to be mounted.

If the listflags shell variable is set to ‘x’, ‘a’ or ‘A’, or any
combination thereof (e.g., ‘xA’), they are used as flags to ,
making it act like ‘ls -xF’, ‘ls -Fa’, ‘ls -FA’ or a combination
(e.g., ‘ls -FxA’).
On machines where ‘ls -C’ is not the default, acts like ‘ls -CF’,
unless listflags contains an ‘x’, in which case it acts like ‘ls -xF’.
passes its arguments to (1) if it is given any switches,
so ‘alias ls ls-F’ generally does the right thing.

The ls-F builtin can list files using different colors depending on the
filetype or extension. See the color variable and the
LS_COLORS environment variable.

migrate [] |% … (+)

migrate – (+)  
The first form migrates the process or job to the site specified or the
default site determined by the system path.
The second form is equivalent to ‘migrate – $$’: it migrates the
current process to the specified site. Migrating the shell
itself can cause unexpected behavior, because the shell
does not like to lose its tty. (TCF only)

newgrp [] (+)  
Equivalent to ‘exec newgrp’; see (1).
Available only if the shell was so compiled;
see the version shell variable.

nice [+] []  
Sets the scheduling priority for the shell to , or, without
, to 4. With , runs at the appropriate
priority.
The greater the , the less cpu
the process gets. The super-user may specify negative
priority by using ‘nice -number …’. Command is always
executed in a sub-shell, and the restrictions placed on
commands in simple statements apply.

nohup []  
With , runs such that it will ignore hangup signals.
Note that commands may set their own response to hangups, overriding .
Without an argument (allowed in only a shell script), causes the shell to
ignore hangups for the remainder of the script.
See also Signal handling and the builtin command.

notify [% …]  
Causes the shell to notify the user asynchronously when the status of any
of the specified jobs (or, without %, the current job) changes,
instead of waiting until the next prompt as is usual.
may be a number, a string, ‘’, ‘%’, ‘+’ or ‘-’ as described
under Jobs.
See also the notify shell variable.

onintr [|]  
Controls the action of the shell on interrupts. Without arguments,
restores the default action of the shell on interrupts,
which is to terminate shell scripts or to return to the
terminal command input level.
With ‘-’, causes all interrupts to be ignored.
With , causes the shell to execute a ‘goto ’
when an interrupt is received or a child process terminates because it was
interrupted.

is ignored if the shell is running detached and in system
startup files (see FILES), where interrupts are disabled anyway.

popd [-p] [-l] [-n|-v] [+]  
Without arguments, pops the directory stack and returns to the new top directory.
With a number ‘+’, discards the ’th entry in the stack.

Finally, all forms of print the final directory stack,
just like . The pushdsilent shell variable can be set to
prevent this and the -p flag can be given to override pushdsilent.
The -l, -n and -v flags have the same effect on
as on . (+)

printenv [] (+)  
Prints the names and values of all environment variables or,
with , the value of the environment variable .

pushd [-p] [-l] [-n|-v] [|+]  
Without arguments, exchanges the top two elements of the directory stack.
If pushdtohome is set, without arguments does ‘pushd ~’,
like . (+)
With , pushes the current working directory onto the directory
stack and changes to .
If is ‘-’ it is interpreted as the previous working directory
(see Filename substitution). (+)
If dunique is set, removes any instances of
from the stack before pushing it onto the stack. (+)
With a number ‘+’, rotates the th element of the
directory stack around to be the top element and changes to it.
If dextract is set, however, ‘pushd +’ extracts the th
directory, pushes it onto the top of the stack and changes to it. (+)

Finally, all forms of print the final directory stack,
just like . The pushdsilent shell variable can be set to
prevent this and the -p flag can be given to override pushdsilent.
The -l, -n and -v flags have the same effect on
as on . (+)

rehash
Causes the internal hash table of the contents of the
directories in the path variable to be recomputed. This is
needed if new commands are added to directories in path
while you are logged in. This should be necessary only if
you add commands to one of your own directories, or if a
systems programmer changes the contents of one of the
system directories. Also flushes the cache of home directories
built by tilde expansion.

repeat  
The specified ,
which is subject to the same restrictions as the
in the one line statement above, is executed times.
I/O redirections occur exactly once, even if is 0.

rootnode //(+)  
Changes the rootnode to //, so that ‘/’ will be interpreted
as ‘//’. (Domain/OS only)

sched (+)
sched [+] (+)

sched – (+)  
The first form prints the scheduled-event list.
The sched shell variable may be set to define the format in which
the scheduled-event list is printed.
The second form adds to the scheduled-event list.
For example,

TagDescription

> sched 11:00 echo It#146;s eleven o#146;clock.

causes the shell to echo ‘It’s eleven o’clock.’ at 11 AM.
The time may be in 12-hour AM/PM format

TagDescription

> sched 5pm set prompt=’[%h] It#146;s after 5; go home: >’

or may be relative to the current time:

TagDescription

> sched +2:15 /usr/lib/uucp/uucico -r1 -sother

A relative time specification may not use AM/PM format.
The third form removes item from the event list:

TagDescription

> sched

1 Wed Apr 4 15:42 /usr/lib/uucp/uucico -r1 -sother

2 Wed Apr 4 17:00 set prompt=[%h] It’s after 5; go home: >

> sched -2

> sched

1 Wed Apr 4 15:42 /usr/lib/uucp/uucico -r1 -sother

A command in the scheduled-event list is executed just before the first
prompt is printed after the time when the command is scheduled.
It is possible to miss the exact time when the command is to be run, but
an overdue command will execute at the next prompt.
A command which comes due while the shell
is waiting for user input is executed immediately.
However, normal operation of an already-running command will not
be interrupted so that a scheduled-event list element may be run.

This mechanism is similar to, but not the same as, the (1)
command on some Unix systems.
Its major disadvantage is that it may not run a command at exactly the
specified time.
Its major advantage is that because runs directly from
the shell, it has access to shell variables and other structures.
This provides a mechanism for changing one’s working environment
based on the time of day.

set
set
set =
set [-r] [-f|-l] =() … (+)
set =
set -r (+)
set -r … (+)

set -r = … (+)  
The first form of the command prints the value of all shell variables.
Variables which contain more than a single word print as a
parenthesized word list.
The second form sets to the null string.
The third form sets to the single .
The fourth form sets to the list of words in
. In all cases the value is command and filename expanded.
If -r is specified, the value is set read-only. If -f or -l are
specified, set only unique words keeping their order.
-f prefers the first occurrence of a word, and -l the last.
The fifth form sets the ’th component of name to ;
this component must already exist.
The sixth form lists only the names of all shell variables that are read-only.
The seventh form makes read-only, whether or not it has a value.
The eighth form is the same as the third form, but
make read-only at the same time.

These arguments can be repeated to set and/or make read-only multiple variables
in a single set command. Note, however, that variable expansion
happens for all arguments before any setting occurs. Note also that ‘=’ can
be adjacent to both and or separated from both by
whitespace, but cannot be adjacent to only one or the other.
See also the builtin command.

setenv [[]]  
Without arguments, prints the names and values of all environment variables.
Given , sets the environment variable to
or, without , to the null string.

setpath (+)  
Equivalent to (1). (Mach only)

setspath LOCAL|| … (+)  
Sets the system execution path. (TCF only)

settc (+)  
Tells the shell to believe that the terminal capability
(as defined in (5)) has the value .
No sanity checking is done.
Concept terminal users may have to ‘settc xn no’ to get proper
wrapping at the rightmost column.

setty [-d|-q|-x] [-a] [[+|]] (+)  
Controls which tty modes (see Terminal management)
the shell does not allow to change.
-d, -q or -x tells to act
on the ‘edit’, ‘quote’ or ‘execute’ set of tty modes respectively; without
-d, -q or -x, ‘execute’ is used.

Without other arguments, lists the modes in the chosen set
which are fixed on (‘+mode’) or off (‘-mode’).
The available modes, and thus the display, vary from system to system.
With -a, lists all tty modes in the chosen set
whether or not they are fixed.
With +, or , fixes on or off
or removes control from in the chosen set.
For example, ‘setty +echok echoe’ fixes ‘echok’ mode on and allows commands
to turn ‘echoe’ mode on or off, both when the shell is executing commands.

setxvers [] (+)  
Set the experimental version prefix to , or removes it
if is omitted. (TCF only)

shift []  
Without arguments, discards argv[1] and shifts the members of
argv to the left. It is an error for argv not to be set or to have
less than one word as value. With , performs the
same function on .

source [-h] [ …]  
The shell reads and executes commands from .
The commands are not placed on the history list.
If any are given, they are placed in argv. (+)
commands may be nested;
if they are nested too deeply the shell may run out of file descriptors.
An error in a at any level terminates all nested
commands.
With -h, commands are placed on the history list instead of being
executed, much like ‘history -L’.

stop %| …  
Stops the specified jobs or processes which are executing in the background.
may be a number, a string, ‘’, ‘%’, ‘+’ or ‘-’ as described
under Jobs.
There is no default ; saying just ‘stop’ does not stop
the current job.

suspend
Causes the shell to stop in its tracks, much as if it had
been sent a stop signal with ^Z. This is most often used to
stop shells started by (1).

switch ()
case :
TagDescription



breaksw

The next sections of this manual describe all of the availableand…

default:

TagDescription



breaksw

TagDescription

endsw
Each case label is successively matched, against the
specified which is first command and filename expanded.
The file metacharacters ‘*’, ‘?’ and ‘[…]’ may be used
in the case labels, which are variable expanded. If none
of the labels match before a ‘default’ label is found, then
the execution begins after the default label. Each case
label and the default label must appear at the beginning of
a line. The command causes execution to continue
after the . Otherwise control may fall through case
labels and default labels as in C. If no label matches and
there is no default, execution continues after the .

telltc (+)  
Lists the values of all terminal capabilities (see (5)).

termname [] (+)  
Tests if (or the current value of TERM if no
is given) has an entry in the hosts termcap(5) or
terminfo(5) database. Prints the terminal type to stdout and returns 0
if an entry is present otherwise returns 1.

time []  
Executes (which must be a simple command, not an alias,
a pipeline, a command list or a parenthesized command list)
and prints a time summary as described under the time variable.
If necessary, an extra shell is created to print the time statistic when
the command completes.
Without , prints a time summary for the current shell and its
children.

umask []  
Sets the file creation mask to , which is given in octal.
Common values for the mask are
002, giving all access to the group and read and execute access to others, and
022, giving read and execute access to the group and others.
Without , prints the current file creation mask.

unalias  
Removes all aliases whose names match .
‘unalias *’ thus removes all aliases.
It is not an error for nothing to be ed.

uncomplete (+)  
Removes all completions whose names match .
‘uncomplete *’ thus removes all completions.
It is not an error for nothing to be d.

unhash
Disables use of the internal hash table to speed location of
executed programs.

universe (+)  
Sets the universe to . (Masscomp/RTU only)

unlimit [-h] []  
Removes the limitation on or, if no is
specified, all limitations.
With -h, the corresponding hard limits are removed.
Only the super-user may do this.
Note that unlimit may not exit successful, since most systems
do not allow to be unlimited.

unset  
Removes all variables whose names match , unless they are read-only.
‘unset *’ thus removes all variables unless they are read-only;
this is a bad idea.
It is not an error for nothing to be .

unsetenv  
Removes all environment variables whose names match .
‘unsetenv *’ thus removes all environment variables;
this is a bad idea.
It is not an error for nothing to be ed.

ver [ []] (+)  
Without arguments, prints SYSTYPE. With , sets SYSTYPE
to . With and , executes
under . may be ‘bsd4.3’ or ‘sys5.3’.
(Domain/OS only)

wait
The shell waits for all background jobs. If the shell is interactive, an
interrupt will disrupt the wait and cause the shell to print the names and job
numbers of all outstanding jobs.

warp (+)  
Sets the universe to . (Convex/OS only)

watchlog (+)  
An alternate name for the builtin command (q.v.).
Available only if the shell was so compiled;
see the version shell variable.

where (+)  
Reports all known instances of , including aliases, builtins and
executables in path.

which (+)  
Displays the command that will be executed by the shell after substitutions,
path searching, etc.
The builtin command is just like (1), but it correctly reports
aliases and builtins and is 10 to 100 times faster.
See also the editor command.

while ()

end
Executes the commands between the and the matching
while (an expression, as described under Expressions)
evaluates non-zero.
and must appear alone on their input lines.
and may be used to terminate or continue the
loop prematurely.
If the input is a terminal, the user is prompted the first time
through the loop as with .

If set, each of these aliases executes automatically at the indicated time.
They are all initially undefined.

TagDescription

beepcmd
Runs when the shell wants to ring the terminal bell.

cwdcmd
Runs after every change of working directory. For example, if the user is
working on an X window system using (1) and a re-parenting window
manager that supports title bars such as (1) and does

TagDescription

> alias cwdcmd ’echo -n “^[]2;${HOST}:$cwd ^G”’

then the shell will change the title of the running (1)
to be the name of the host, a colon, and the full current working directory.
A fancier way to do that is

TagDescription

> alias cwdcmd ’echo -n “^[]2;${HOST}:$cwd^G^[]1;${HOST}^G”’

This will put the hostname and working directory on the title bar but
only the hostname in the icon manager menu.

Note that putting a , or in
may cause an infinite loop. It is the author’s opinion that anyone doing
so will get what they deserve.

jobcmd
Runs before each command gets executed, or when the command changes state.
This is similar to , but it does not print builtins.

TagDescription

> alias jobcmd ’echo -n “^[]2\;\!#^G”’

then executing will put the command string in the xterm title bar.

helpcommand  
Invoked by the run-help editor command. The command name for which help
is sought is passed as sole argument.
For example, if one does

TagDescription

> alias helpcommand ’\!:1 –help’

then the help display of the command itself will be invoked, using the GNU
help calling convention.
Currently there is no easy way to account for various calling conventions (e.g.,
the customary Unix ‘-h’), except by using a table of many commands.

periodic
Runs every tperiod minutes. This provides a convenient means for
checking on common but infrequent changes such as new mail. For example,
if one does

TagDescription

> set tperiod = 30

> alias periodic checknews

then the (1) program runs every 30 minutes.
If is set but tperiod is unset or set to 0,
behaves like .

precmd
Runs just before each prompt is printed. For example, if one does

TagDescription

> alias precmd date

then (1) runs just before the shell prompts for each command.
There are no limits on what can be set to do, but discretion
should be used.

postcmd
Runs before each command gets executed.

TagDescription

> alias postcmd ’echo -n “^[]2\;\!#^G”’

then executing will put the command string in the xterm title bar.

shell
Specifies the interpreter for executable scripts which do not themselves
specify an interpreter. The first word should be a full path name to the
desired interpreter (e.g., ‘/bin/csh’ or ‘/usr/local/bin/tcsh’).

The variables described in this section have special meaning to the shell.

If set, each of these aliases executes automatically at the indicated time. They are all initially undefined.The variables described in this section have special meaning to the shell.

The shell sets addsuffix, argv, autologout, csubstnonl, command, echo_style,
edit, gid, group, home, loginsh, oid, path,
prompt, prompt2, prompt3, shell, shlvl,
tcsh, term, tty, uid, user and version at
startup; they do not change thereafter unless changed by the user. The shell
updates cwd, dirstack, owd and status when necessary,
and sets logout on logout.

The shell synchronizes afsuser, group, home, path, shlvl,
term and user with the environment variables of the same names:
whenever the environment variable changes the shell changes the corresponding
shell variable to match (unless the shell variable is read-only) and vice
versa. Note that although cwd and PWD have identical meanings, they
are not synchronized in this manner, and that the shell automatically
interconverts the different formats of path and PATH.

TagDescription

addsuffix (+)  
If set, filename completion adds ‘/’ to the end of directories and a space
to the end of normal files when they are matched exactly.
Set by default.

afsuser (+)  
If set, autologout’s autolock feature uses its value instead of
the local username for kerberos authentication.

ampm (+)
If set, all times are shown in 12-hour AM/PM format.

argv
The arguments to the shell. Positional parameters are taken from argv,
i.e., ‘$1’ is replaced by ‘$argv[1]’, etc.
Set by default, but usually empty in interactive shells.

autocorrect (+)  
If set, the editor command is invoked automatically before
each completion attempt.

autoexpand (+)  
If set, the editor command is invoked automatically
before each completion attempt.

autolist (+)  
If set, possibilities are listed after an ambiguous completion.
If set to ‘ambiguous’, possibilities are listed only when no new
characters are added by completion.

autologout (+)  
The first word is the number of minutes of inactivity before automatic
logout. The optional second word is the number of minutes of inactivity
before automatic locking.
When the shell automatically logs out,
it prints ‘auto-logout’, sets the variable logout to ‘automatic’ and exits.
When the shell automatically locks, the user is required to enter his password
to continue working. Five incorrect attempts result in automatic logout.
Set to ‘60’ (automatic logout after 60 minutes, and no locking) by default
in login and superuser shells, but not if the shell thinks it is running
under a window system (i.e., the DISPLAY environment variable is set),
the tty is a pseudo-tty (pty) or the shell was not so compiled (see the
version shell variable).
See also the afsuser and logout shell variables.

backslash_quote (+)  
If set, backslashes (‘#146;) always quote ‘#146;, ‘’’, and ‘”’. This may make
complex quoting tasks easier, but it can cause syntax errors in (1)
scripts.

catalog
The file name of the message catalog.
If set, tcsh use ‘tcsh.${catalog}’ as a message catalog instead of
default ‘tcsh’.

cdpath
A list of directories in which should search for
subdirectories if they aren’t found in the current directory.

color
If set, it enables color display for the builtin ls-F and it passes
–color=auto to ls. Alternatively, it can be set to only
ls-F or only ls to enable color to only one command. Setting
it to nothing is equivalent to setting it to (ls-F ls).

colorcat
If set, it enables color escape sequence for NLS message files.
And display colorful NLS messages.

command (+)  
If set, the command which was passed to the shell with the -c flag (q.v.).

complete (+)  
If set to ‘enhance’, completion 1) ignores case and 2) considers
periods, hyphens and underscores (‘.’, ‘-’ and ‘_’) to be word
separators and hyphens and underscores to be equivalent. If set to
‘igncase’, the completion becomes case insensitive.

continue (+)  
If set to a list of commands, the shell will continue the listed
commands, instead of starting a new one.

continue_args (+)  
Same as continue, but the shell will execute:

TagDescription

echo ‘pwd‘ $argv > ~/.<cmd>_pause; %<cmd>

correct (+)  
If set to ‘cmd’, commands are automatically spelling-corrected.
If set to ‘complete’, commands are automatically completed.
If set to ‘all’, the entire command line is corrected.

csubstnonl (+)  
If set, newlines and carriage returns in command substitution are
replaced by spaces. Set by default.

cwd
The full pathname of the current directory.
See also the dirstack and owd shell variables.

dextract (+)  
If set, ‘pushd +’ extracts the th directory from the directory
stack rather than rotating it to the top.

dirsfile (+)  
The default location in which ‘dirs -S’ and ‘dirs -L’ look for
a history file. If unset, is used.
Because only is normally sourced before ,
dirsfile should be set in rather than .

dirstack (+)  
An array of all the directories on the directory stack.
‘$dirstack[1]’ is the current working directory, ‘$dirstack[2]’
the first directory on the stack, etc.
Note that the current working directory is ‘$dirstack[1]’ but ‘=0’ in
directory stack substitutions, etc.
One can change the stack arbitrarily by setting dirstack,
but the first element (the current working directory) is always correct.
See also the cwd and owd shell variables.

dspmbyte (+)  
Has an affect iff ’dspm’ is listed as part of the version shell variable.
If set to ‘euc’, it enables display and editing EUC-kanji(Japanese) code.
If set to ‘sjis’, it enables display and editing Shift-JIS(Japanese) code.
If set to ‘big5’, it enables display and editing Big5(Chinese) code.
If set to ‘utf8’, it enables display and editing Utf8(Unicode) code.
If set to the following format, it enables display and editing of original
multi-byte code format:

TagDescription

> set dspmbyte = 0000….(256 bytes)….0000

The table requires just 256 bytes. Each character of 256 characters
corresponds (from left to right) to the ASCII codes 0x00, 0x01, … 0xff. Each
character
is set to number 0,1,2 and 3. Each number has the following meaning:

0 … not used for multi-byte characters.

1 … used for the first byte of a multi-byte character.

2 … used for the second byte of a multi-byte character.

3 … used for both the first byte and second byte of a multi-byte character.

Example:

If set to ‘001322’, the first character (means 0x00 of the ASCII code) and
second character (means 0x01 of ASCII code) are set to ‘0’. Then, it is not
used for multi-byte characters. The 3rd character (0x02) is set to ’1’,
indicating that it is used for the first byte of a multi-byte character.
The 4th character(0x03) is set ’3’. It is used for both the first byte and
the second byte of a multi-byte character. The 5th and 6th characters
(0x04,0x05) are set to ’2’, indicating that they are used for the second
byte of a multi-byte character.

The GNU fileutils version of ls cannot display multi-byte
filenames without the -N ( –literal ) option. If you are using
this version, set the second word of dspmbyte to “ls”. If not, for
example, “ls-F -l” cannot display multi-byte filenames.

Note:

This variable can only be used if KANJI and DSPMBYTE has been defined at
compile time.

dunique (+)  
If set, removes any instances of
from the stack before pushing it onto the stack.

echo
If set, each command with its arguments is echoed just before it is
executed. For non-builtin commands all expansions occur before
echoing. Builtin commands are echoed before command and filename
substitution, because these substitutions are then done selectively.
Set by the -x command line option.

echo_style (+)  
The style of the builtin. May be set to

TagDescription

bsd

Don’t echo a newline if the first argument is ‘-n’.

sysv

Recognize backslashed escape sequences in echo strings.

both

Recognize both the ‘-n’ flag and backslashed escape sequences; the default.

none

Recognize neither.

Set by default to the local system default. The BSD and System V
options are described in the (1) man pages on the appropriate
systems.

edit (+)
If set, the command-line editor is used. Set by default in interactive
shells.

ellipsis (+)  
If set, the ‘%c’/‘%.’ and ‘%C’ prompt sequences (see the prompt
shell variable) indicate skipped directories with an ellipsis (‘…’)
instead of ‘/<skipped>’.

fignore (+)  
Lists file name suffixes to be ignored by completion.

filec
In , completion is always used and this variable is ignored
by default. If
edit is unset, then the traditional completion is used.
If set in , filename completion is used.

gid (+)
The user’s real group ID.

group (+)
The user’s group name.

histchars  
A string value determining the characters used in History
substitution
(q.v.). The first character of its value is used as
the history substitution character, replacing the default character
‘!’. The second character of its value replaces the character ‘^’ in
quick substitutions.

histdup (+)  
Controls handling of duplicate entries in the history list. If set to
‘all’ only unique history events are entered in the history list. If
set to ‘prev’ and the last history event is the same as the current
command, then the current command is not entered in the history. If
set to ‘erase’ and the same event is found in the history list, that
old event gets erased and the current one gets inserted. Note that the
‘prev’ and ‘all’ options renumber history events so there are no gaps.

histfile (+)  
The default location in which ‘history -S’ and ‘history -L’ look for
a history file. If unset, is used. histfile is
useful when sharing the same home directory between different machines,
or when saving separate histories on different terminals. Because only
is normally sourced before ,
histfile should be set in rather than
.

histlit (+)  
If set, builtin and editor commands and the savehist mechanism
use the literal (unexpanded) form of lines in the history list. See
also the editor command.

history
The first word indicates the number of history events to save. The
optional second word (+) indicates the format in which history is
printed; if not given, ‘%h\t%T\t%R\n’ is used. The format sequences
are described below under prompt; note the variable meaning of
‘%R’. Set to ‘100’ by default.

home
Initialized to the home directory of the invoker. The filename
expansion of ‘’ refers to this variable.

ignoreeof  
If set to the empty string or ‘0’ and the input device is a terminal,
the command (usually generated by the user by typing
‘^D’ on an empty line) causes the shell to print ‘Use “exit” to leave
tcsh.’ instead of exiting. This prevents the shell from accidentally
being killed. Historically this setting exited after 26 successive
EOF’s to avoid infinite loops. If set to a number , the shell
ignores consecutive s and exits on the
th. (+) If unset, ‘1’ is used, i.e., the shell exits on a
single ‘^D’.

implicitcd (+)  
If set, the shell treats a directory name typed as a command as though
it were a request to change to that directory. If set to ,
the change of directory is echoed to the standard output. This behavior
is inhibited in non-interactive shell scripts, or for command strings
with more than one word. Changing directory takes precedence over
executing a like-named command, but it is done after alias
substitutions. Tilde and variable expansions work as expected.

inputmode (+)  
If set to ‘insert’ or ‘overwrite’, puts the editor into that input mode
at the beginning of each line.

killdup (+)  
Controls handling of duplicate entries in the kill ring. If set to
‘all’ only unique strings are entered in the kill ring. If set to
‘prev’ and the last killed string is the same as the current killed
string, then the current string is not entered in the ring. If set
to ‘erase’ and the same string is found in the kill ring, the old
string is erased and the current one is inserted.

killring (+)  
Indicates the number of killed strings to keep in memory. Set to ‘30’
by default. If unset or set to less than ‘2’, the shell will only
keep the most recently killed string.
Strings are put in the killring by the editor commands that delete
(kill) strings of text, e.g. ,
, etc, as well as the command.
The editor command will yank the most recently killed string
into the command-line, while (see Editor commands)
can be used to yank earlier killed strings.

listflags (+)  
If set to ‘x’, ‘a’ or ‘A’, or any combination thereof (e.g., ‘xA’), they
are used as flags to , making it act like ‘ls -xF’, ‘ls
-Fa’, ‘ls -FA’ or a combination (e.g., ‘ls -FxA’): ‘a’ shows all
files (even if they start with a ‘.’), ‘A’ shows all files but ‘.’ and
‘..’, and ‘x’ sorts across instead of down. If the second word of
listflags is set, it is used as the path to ‘ls(1)’.

listjobs (+)  
If set, all jobs are listed when a job is suspended. If set to ‘long’,
the listing is in long format.

listlinks (+)  
If set, the builtin command shows the type of file to which
each symbolic link points.

listmax (+)  
The maximum number of items which the editor command
will list without asking first.

listmaxrows (+)  
The maximum number of rows of items which the editor
command will list without asking first.

loginsh (+)  
Set by the shell if it is a login shell. Setting or unsetting it
within a shell has no effect. See also shlvl.

logout (+)  
Set by the shell to ‘normal’ before a normal logout, ‘automatic’ before
an automatic logout, and ‘hangup’ if the shell was killed by a hangup
signal (see Signal handling). See also the autologout
shell variable.

mail
The names of the files or directories to check for incoming mail,
separated by whitespace, and optionally preceded by a numeric word.
Before each prompt, if 10 minutes have passed since the last check, the
shell checks each file and says ‘You have new mail.’ (or, if mail
contains multiple files, ‘You have new mail in .’) if the
filesize is greater than zero in size and has a modification time
greater than its access time.

If you are in a login shell, then no mail file is reported unless it has
been modified after the time the shell has started up, to prevent
redundant notifications. Most login programs will tell you whether or not
you have mail when you log in.

If a file specified in mail is a directory, the shell will count each
file within that directory as a separate message, and will report ‘You have
mails.’ or ‘You have mails in .’ as appropriate.
This functionality is provided primarily for those systems which store mail
in this manner, such as the Andrew Mail System.

If the first word of mail is numeric it is taken as a different mail
checking interval, in seconds.

Under very rare circumstances, the shell may report ‘You have mail.’ instead
of ‘You have new mail.’

matchbeep (+)  
If set to ‘never’, completion never beeps.
If set to ‘nomatch’, it beeps only when there is no match.
If set to ‘ambiguous’, it beeps when there are multiple matches.
If set to ‘notunique’, it beeps when there is one exact and other longer matches.
If unset, ‘ambiguous’ is used.

nobeep (+)  
If set, beeping is completely disabled.
See also visiblebell.

noclobber  
If set, restrictions are placed on output redirection to insure that files
are not accidentally destroyed and that ‘>>’ redirections refer to existing
files, as described in the Input/output section.

noding
If set, disable the printing of ‘DING!’ in the prompt time
specifiers at the change of hour.

noglob
If set, Filename substitution and Directory stack substitution
(q.v.) are inhibited. This is most useful in shell scripts which do not deal
with filenames, or after a list of filenames has been obtained and further
expansions are not desirable.

nokanji (+)  
If set and the shell supports Kanji (see the version shell variable),
it is disabled so that the meta key can be used.

nonomatch  
If set, a Filename substitution or Directory stack substitution
(q.v.) which does not match any
existing files is left untouched rather than causing an error.
It is still an error for the substitution to be
malformed, e.g., ‘echo [’ still gives an error.

nostat (+)  
A list of directories (or glob-patterns which match directories; see
Filename substitution) that should not be (2)ed during a
completion operation. This is usually used to exclude directories which
take too much time to (2), for example .

notify
If set, the shell announces job completions asynchronously.
The default is to present job completions just before printing a prompt.

oid (+)
The user’s real organization ID. (Domain/OS only)

owd (+)
The old working directory, equivalent to the ‘-’ used by and .
See also the cwd and dirstack shell variables.

path
A list of directories in which to look for executable commands.
A null word specifies the current directory.
If there is no path variable then only full path names will execute.
path is set by the shell at startup from the PATH environment
variable or, if PATH does not exist, to a system-dependent default
something like ‘(/usr/local/bin /usr/bsd /bin /usr/bin .)’.
The shell may put ‘.’ first or last in path or omit it entirely
depending on how it was compiled; see the version shell variable.
A shell which is given neither the -c nor the -t option
hashes the contents of the directories in path after
reading and each time path is reset.
If one adds a new command to a directory in path while the shell
is active, one may need to do a for the shell to find it.

printexitvalue (+)  
If set and an interactive program exits with a non-zero status, the shell
prints ‘Exit status’.

prompt
The string which is printed before reading each command from the terminal.
prompt may include any of the following formatting sequences (+), which
are replaced by the given information:

TagDescription

%/

The current working directory.

%~

The current working directory, but with one’s home directory
represented by ‘~’ and other users’ home directories represented by
‘~user’ as per Filename substitution. ‘~user’ substitution
happens only if the shell has already used ‘~’ in a pathname
in the current session.

%c[[0]], %.[[0]]
 
The trailing component of the current working directory, or
trailing components if a digit is given.
If begins with ‘0’, the number of skipped components precede
the trailing component(s) in the format ‘/<>trailing’.
If the ellipsis shell variable is set, skipped components
are represented by an ellipsis so the whole becomes ‘…trailing’.
‘~’ substitution is done as in ‘%~’ above, but the ‘~’ component
is ignored when counting trailing components.

%C

Like %c, but without ‘~’ substitution.

%h, %!, !
 
The current history event number.

%M

The full hostname.

%m

The hostname up to the first ‘.’.

%S (%s)
 
Start (stop) standout mode.

%B (%b)
 
Start (stop) boldfacing mode.

%U (%u)
 
Start (stop) underline mode.

%t, %@
 
The time of day in 12-hour AM/PM format.

%T

Like ‘%t’, but in 24-hour format (but see the ampm shell variable).

%p

The ‘precise’ time of day in 12-hour AM/PM format, with seconds.

%P

Like ‘%p’, but in 24-hour format (but see the ampm shell variable).

\
is parsed as in .

^
is parsed as in .

%%

A single ‘%’.

%n

The user name.

%j

The number of jobs.

%d

The weekday in ‘Day’ format.

%D

The day in ‘dd’ format.

%w

The month in ‘Mon’ format.

%W

The month in ‘mm’ format.

%y

The year in ‘yy’ format.

%Y

The year in ‘yyyy’ format.

%l

The shell’s tty.

%L

Clears from the end of the prompt to end of the display or the end of the line.

%$

Expands the shell or environment variable name immediately after the ‘$’.

%#

‘>’ (or the first character of the promptchars shell variable)
for normal users, ‘#’ (or the second character of promptchars)
for the superuser.

%{%}
 
Includes as a literal escape sequence.
It should be used only to change terminal attributes and
should not move the cursor location. This
cannot be the last sequence in prompt.

%?

The return code of the command executed just before the prompt.

%R

In prompt2, the status of the parser.
In prompt3, the corrected string.
In history, the history string.

‘%B’, ‘%S’, ‘%U’ and ‘%{%}’ are available in only
eight-bit-clean shells; see the version shell variable.

The bold, standout and underline sequences are often used to distinguish a
superuser shell. For example,

TagDescription

> set prompt = “%m [%h] %B[%@]%b [%/] you rang? ”

tut [37] [2:54pm] [/usr/accts/sys] you rang? _

If ‘%t’, ‘%@’, ‘%T’, ‘%p’, or ‘%P’ is used, and noding is not set,
then print ‘DING!’ on the change of hour (i.e, ‘:00’ minutes) instead of
the actual time.

Set by default to ‘%# ’ in interactive shells.

prompt2 (+)  
The string with which to prompt in and loops and
after lines ending in ‘#146;.
The same format sequences may be used as in prompt (q.v.);
note the variable meaning of ‘%R’.
Set by default to ‘%R? ’ in interactive shells.

prompt3 (+)  
The string with which to prompt when confirming automatic spelling correction.
The same format sequences may be used as in prompt (q.v.);
note the variable meaning of ‘%R’.
Set by default to ‘CORRECT>%R (y|n|e|a)? ’ in interactive shells.

promptchars (+)  
If set (to a two-character string), the ‘%#’ formatting sequence in the
prompt shell variable is replaced with the first character for
normal users and the second character for the superuser.

pushdtohome (+)  
If set, without arguments does ‘pushd ~’, like .

pushdsilent (+)  
If set, and do not print the directory stack.

recexact (+)  
If set, completion completes on an exact match even if a longer match is
possible.

recognize_only_executables (+)  
If set, command listing displays only files in the path that are
executable. Slow.

rmstar (+)  
If set, the user is prompted before ‘rm *’ is executed.

rprompt (+)  
The string to print on the right-hand side of the screen (after
the command input) when the prompt is being displayed on the left.
It recognizes the same formatting characters as prompt.
It will automatically disappear and reappear as necessary, to ensure that
command input isn’t obscured, and will appear only if the prompt,
command input, and itself will fit together on the first line.
If edit isn’t set, then rprompt will be printed after
the prompt and before the command input.

savedirs (+)  
If set, the shell does ‘dirs -S’ before exiting.
If the first word is set to a number, at most that many directory stack
entries are saved.

savehist
If set, the shell does ‘history -S’ before exiting.
If the first word is set to a number, at most that many lines are saved.
(The number must be less than or equal to history.)
If the second word is set to ‘merge’, the history list is merged with
the existing history file instead of replacing it (if there is one) and
sorted by time stamp and the most recent events are retained. (+)

sched (+)
The format in which the builtin command prints scheduled events;
if not given, ‘%h\t%T\t%R\n’ is used.
The format sequences are described above under prompt;
note the variable meaning of ‘%R’.

shell
The file in which the shell resides. This is used in forking
shells to interpret files which have execute bits set, but
which are not executable by the system. (See the description
of Builtin and non-builtin command execution.) Initialized to the
(system-dependent) home of the shell.

shlvl (+)
The number of nested shells.
Reset to 1 in login shells.
See also loginsh.

status
The status returned by the last command. If it terminated
abnormally, then 0200 is added to the status. Builtin commands
which fail return exit status ‘1’, all other builtin commands
return status ‘0’.

symlinks (+)  
Can be set to several different values to control symbolic link (‘symlink’)
resolution:

If set to ‘chase’, whenever the current directory changes to a directory
containing a symbolic link, it is expanded to the real name of the directory
to which the link points. This does not work for the user’s home directory;
this is a bug.

If set to ‘ignore’, the shell tries to construct a current directory
relative to the current directory before the link was crossed.
This means that ing through a symbolic link and then ‘cd ..’ing
returns one to the original directory. This affects only builtin commands
and filename completion.

If set to ‘expand’, the shell tries to fix symbolic links by actually expanding
arguments which look like path names. This affects any command, not just
builtins. Unfortunately, this does not work for hard-to-recognize filenames,
such as those embedded in command options. Expansion may be prevented by
quoting. While this setting is usually the most convenient, it is sometimes
misleading and sometimes confusing when it fails to recognize an argument
which should be expanded. A compromise is to use ‘ignore’ and use the
editor command (bound by default to ^X-n) when necessary.

Some examples are in order. First, let’s set up some play directories:

TagDescription

> cd /tmp

> mkdir from from/src to

> ln -s from/src to/dst

Here’s the behavior with symlinks unset,

TagDescription

> cd /tmp/to/dst; echo $cwd

/tmp/to/dst

> cd ..; echo $cwd

/tmp/from

here’s the behavior with symlinks set to ‘chase’,

TagDescription

> cd /tmp/to/dst; echo $cwd

/tmp/from/src

> cd ..; echo $cwd

/tmp/from

here’s the behavior with symlinks set to ‘ignore’,

TagDescription

> cd /tmp/to/dst; echo $cwd

/tmp/to/dst

> cd ..; echo $cwd

/tmp/to

and here’s the behavior with symlinks set to ‘expand’.

TagDescription

> cd /tmp/to/dst; echo $cwd

/tmp/to/dst

> cd ..; echo $cwd

/tmp/to

> cd /tmp/to/dst; echo $cwd

/tmp/to/dst

> cd “..”; echo $cwd

/tmp/from

> /bin/echo ..

/tmp/to

> /bin/echo “..”

..

Note that ‘expand’ expansion 1) works just like ‘ignore’ for builtins
like , 2) is prevented by quoting, and 3) happens before
filenames are passed to non-builtin commands.

tcsh (+)
The version number of the shell in the format ‘R.VV.PP’,
where ‘R’ is the major release number, ‘VV’ the current version
and ‘PP’ the patchlevel.

term
The terminal type. Usually set in as described under
Startup and shutdown.

time
If set to a number, then the builtin (q.v.) executes automatically
after each command which takes more than that many CPU seconds.
If there is a second word, it is used as a format string for the output
of the builtin. (u) The following sequences may be used in the
format string:

TagDescription

%U

The time the process spent in user mode in cpu seconds.

%S

The time the process spent in kernel mode in cpu seconds.

%E

The elapsed (wall clock) time in seconds.

%P

The CPU percentage computed as (%U + %S) / %E.

%W

Number of times the process was swapped.

%X

The average amount in (shared) text space used in Kbytes.

%D

The average amount in (unshared) data/stack space used in Kbytes.

%K

The total space used (%X + %D) in Kbytes.

%M

The maximum memory the process had in use at any time in Kbytes.

%F

The number of major page faults (page needed to be brought from disk).

%R

The number of minor page faults.

%I

The number of input operations.

%O

The number of output operations.

%r

The number of socket messages received.

%s

The number of socket messages sent.

%k

The number of signals received.

%w

The number of voluntary context switches (waits).

%c

The number of involuntary context switches.

Only the first four sequences are supported on systems without BSD resource
limit functions.
The default time format is ‘%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww’ for
systems that support resource usage reporting and ‘%Uu %Ss %E %P’ for
systems that do not.

Under Sequent’s DYNIX/ptx, %X, %D, %K, %r and %s are not
available, but the following additional sequences are:

%Y

The number of system calls performed.

%Z

The number of pages which are zero-filled on demand.

%i

The number of times a process’s resident set size was increased by the kernel.

%d

The number of times a process’s resident set size was decreased by the kernel.

%l

The number of read system calls performed.

%m

The number of write system calls performed.

%p

The number of reads from raw disk devices.

%q

The number of writes to raw disk devices.

and the default time format is ‘%Uu %Ss %E %P %I+%Oio %Fpf+%Ww’.
Note that the CPU percentage can be higher than 100% on multi-processors.

tperiod (+)  
The period, in minutes, between executions of the special alias.

tty (+)
The name of the tty, or empty if not attached to one.

uid (+)
The user’s real user ID.

user
The user’s login name.

verbose
If set, causes the words of each
command to be printed, after history substitution (if any).
Set by the -v command line option.

version (+)  
The version ID stamp. It contains the shell’s version number (see tcsh),
origin, release date, vendor, operating system and machine (see VENDOR,
OSTYPE and MACHTYPE) and a comma-separated
list of options which were set at compile time.
Options which are set by default in the distribution are noted.

TagDescription

8b

The shell is eight bit clean; default

7b

The shell is not eight bit clean

wide

The shell is multibyte encoding clean (like UTF-8)

nls

The system’s NLS is used; default for systems with NLS

lf

Login shells execute before instead of after
and before instead of after
and .

dl

‘.’ is put last in path for security; default

nd

‘.’ is omitted from path for security

vi

-style editing is the default rather than

dtr

Login shells drop DTR when exiting

bye

is a synonym for and
is an alternate name for

al

autologout is enabled; default

kan

Kanji is used if appropriate according to locale settings,
unless the nokanji shell variable is set

sm

The system’s (3) is used

hb

The ‘#!<program> <args>’ convention is emulated when executing shell scripts

ng

The builtin is available

rh

The shell attempts to set the REMOTEHOST environment variable

afs

The shell verifies your password with the kerberos server if local
authentication fails. The afsuser shell variable or the
AFSUSER environment variable override your local username if set.

An administrator may enter additional strings to indicate differences
in the local version.

visiblebell (+)  
If set, a screen flash is used rather than the audible bell.
See also nobeep.

watch (+)
A list of user/terminal pairs to watch for logins and logouts.
If either the user is ‘any’ all terminals are watched for the given user
and vice versa.
Setting watch to ‘(any any)’ watches all users and terminals.
For example,

TagDescription

set watch = (george ttyd1 any console $user any)

reports activity of the user ‘george’ on ttyd1, any user on the console, and
oneself (or a trespasser) on any terminal.

Logins and logouts are checked every 10 minutes by default, but the first
word of watch can be set to a number to check every so many minutes.
For example,

TagDescription

set watch = (1 any any)

reports any login/logout once every minute. For the impatient, the
builtin command triggers a watch report at any time. All current logins
are reported (as with the builtin) when watch is first set.

The who shell variable controls the format of watch reports.

who (+)
The format string for watch messages. The following sequences
are replaced by the given information:

TagDescription

%n

The name of the user who logged in/out.

%a

The observed action, i.e., ‘logged on’, ‘logged off’ or ‘replaced on’.

%l

The terminal (tty) on which the user logged in/out.

%M

The full hostname of the remote host, or ‘local’ if the login/logout was
from the local host.

%m

The hostname of the remote host up to the first ‘.’.
The full name is printed if it is an IP address or an X Window System display.

%M and %m are available on only systems that store the remote hostname in
.
If unset, ‘%n has %a %l from %m.’ is used, or ‘%n has %a %l.’ on systems
which don’t store the remote hostname.

wordchars (+)  
A list of non-alphanumeric characters to be considered part of a word by the
, etc., editor commands.
If unset, ‘*?_-.[]~=’ is used.

ENVIRONMENT

TagDescription

AFSUSER (+)  
Equivalent to the afsuser shell variable.

COLUMNS
The number of columns in the terminal. See Terminal management.

DISPLAY
Used by X Window System (see (1)).
If set, the shell does not set autologout (q.v.).

EDITOR
The pathname to a default editor.
See also the VISUAL environment variable
and the editor command.

GROUP (+)
Equivalent to the group shell variable.

HOME
Equivalent to the home shell variable.

HOST (+)
Initialized to the name of the machine on which the shell
is running, as determined by the (2) system call.

HOSTTYPE (+)  
Initialized to the type of machine on which the shell
is running, as determined at compile time. This variable is obsolete and
will be removed in a future version.

HPATH (+)
A colon-separated list of directories in which the editor
command looks for command documentation.

LANG
Gives the preferred character environment.
See Native Language System support.

LC_CTYPE
If set, only ctype character handling is changed.
See Native Language System support.

LINES
The number of lines in the terminal. See Terminal management.

LS_COLORS  
The format of this variable is reminiscent of the termcap(5)
file format; a colon-separated list of expressions of the form
“”, where “” is a two-character variable name. The
variables with their associated defaults are:

TagDescription
 

TagDescription

no      0

Normal (non-filename) text

fi      0

Regular file

di      01;34

Directory

ln      01;36

Symbolic link

pi      33

Named pipe (FIFO)

so      01;35

Socket

do      01;35

Door

bd      01;33

Block device

cd      01;32

Character device

ex      01;32

Executable file

mi      (none)

Missing file (defaults to fi)

or      (none)

Orphaned symbolic link (defaults to ln)

lc      ^[[

Left code

rc      m

Right code

ec      (none)

End code (replaces lc+no+rc)

You need to include only the variables you want to change from
the default.

File names can also be colorized based on filename extension.
This is specified in the LS_COLORS variable using the syntax
“*ext=string”. For example, using ISO 6429 codes, to color
all C-language source files blue you would specify “*.c=34”.
This would color all files ending in .c in blue (34) color.

Control characters can be written either in C-style-escaped
notation, or in stty-like ^-notation. The C-style notation
adds ^[ for Escape, _ for a normal space character,
and ? for Delete. In addition, the ^[ escape character
can be used to override the default interpretation of ^[,
^, : and =.

Each file will be written as <lc> <color-code>
<rc> <filename> <ec>. If the <ec>
code is undefined, the sequence <lc> <no>
<rc> will be used instead. This is generally more convenient
to use, but less general. The left, right and end codes are
provided so you don’t have to type common parts over and over
again and to support weird terminals; you will generally not
need to change them at all unless your terminal does not use
ISO 6429 color sequences but a different system.

If your terminal does use ISO 6429 color codes, you can
compose the type codes (i.e., all except the lc, rc,
and ec codes) from numerical commands separated by semicolons. The
most common commands are:

TagDescription
 

TagDescription

0

to restore default color

1

for brighter colors

4

for underlined text

5

for flashing text

30

for black foreground

31

for red foreground

32

for green foreground

33

for yellow (or brown) foreground

34

for blue foreground

35

for purple foreground

36

for cyan foreground

37

for white (or gray) foreground

40

for black background

41

for red background

42

for green background

43

for yellow (or brown) background

44

for blue background

45

for purple background

46

for cyan background

47

for white (or gray) background

Not all commands will work on all systems or display devices.

A few terminal programs do not recognize the default end code
properly. If all text gets colorized after you do a directory
listing, try changing the no and fi codes from 0 to the
numerical codes for your standard fore- and background colors.

MACHTYPE (+)  
The machine type (microprocessor class or machine model), as determined at compile time.

NOREBIND (+)  
If set, printable characters are not rebound to .
See Native Language System support.

OSTYPE (+)  
The operating system, as determined at compile time.

PATH
A colon-separated list of directories in which to look for executables.
Equivalent to the path shell variable, but in a different format.

PWD (+)
Equivalent to the cwd shell variable, but not synchronized to it;
updated only after an actual directory change.

REMOTEHOST (+)  
The host from which the user has logged in remotely, if this is the case and
the shell is able to determine it. Set only if the shell was so compiled;
see the version shell variable.

SHLVL (+)
Equivalent to the shlvl shell variable.

SYSTYPE (+)  
The current system type. (Domain/OS only)

TERM
Equivalent to the term shell variable.

TERMCAP
The terminal capability string. See Terminal management.

USER
Equivalent to the user shell variable.

VENDOR (+)  
The vendor, as determined at compile time.

VISUAL
The pathname to a default full-screen editor.
See also the EDITOR environment variable
and the editor command.

FILES

TagDescription

Read first by every shell.
ConvexOS, Stellix and Intel use and
NeXTs use .
A/UX, AMIX, Cray and IRIX have no equivalent in (1),
but read this file in anyway.
Solaris 2.x does not have it either, but reads . (+)

Read by login shells after .
ConvexOS, Stellix and Intel use ,
NeXTs use , Solaris 2.x uses and
A/UX, AMIX, Cray and IRIX use .

(+)
Read by every shell after or its equivalent.

Read by every shell, if doesn’t exist,
after or its equivalent.
This manual uses ‘’ to mean ‘ or,
if is not found, ’.

Read by login shells after
if savehist is set, but see also histfile.

Read by login shells after or .
The shell may be compiled to read before instead of after
and ; see the version shell variable.

(+)
Read by login shells after
if savedirs is set, but see also dirsfile.

Read by login shells at logout.
ConvexOS, Stellix and Intel use and
NeXTs use .
A/UX, AMIX, Cray and IRIX have no equivalent in (1),
but read this file in anyway.
Solaris 2.x does not have it either, but reads . (+)

Read by login shells at logout after or its equivalent.

Used to interpret shell scripts not starting with a ‘#’.

Temporary file for ‘<<’.

Source of home directories for ‘~name’ substitutions.

The order in which startup files are read may differ if the shell was so
compiled; see Startup and shutdown and the version shell variable.

NEW FEATURES (+)

This manual describes as a single entity,
but experienced (1) users will want to pay special attention to
’s new features.

The order in which startup files are read may differ if the shell was so compiled; seeand theshell variable.This manual describesas a single entity, but experienced(1) users will want to pay special attention to’s new features.

A command-line editor, which supports GNU Emacs or (1)-style
key bindings. See The command-line editor and Editor commands.

Programmable, interactive word completion and listing.
See Completion and listing and the and
builtin commands.

Spelling correction (q.v.) of filenames, commands and variables.

Editor commands (q.v.) which perform other useful functions in the middle of
typed commands, including documentation lookup (),
quick editor restarting () and
command resolution ().

An enhanced history mechanism. Events in the history list are time-stamped.
See also the command and its associated shell variables,
the previously undocumented ‘#’ event specifier and new modifiers
under History substitution,
the , , , and
editor commands
and the histlit shell variable.

Enhanced directory parsing and directory stack handling.
See the , , and commands and their associated
shell variables, the description of Directory stack substitution,
the dirstack, owd and symlinks shell variables and
the and editor commands.

Negation in glob-patterns. See Filename substitution.

New File inquiry operators (q.v.) and a
builtin which uses them.

A variety of Automatic, periodic and timed events (q.v.) including
scheduled events, special aliases, automatic logout and terminal locking,
command timing and watching for logins and logouts.

Support for the Native Language System
(see Native Language System support),
OS variant features
(see OS variant support and the echo_style shell variable)
and system-dependent file locations (see FILES).

Extensive terminal-management capabilities. See Terminal management.

New builtin commands including , , ,
, , and (q.v.).

New variables that make useful information easily available to the shell.
See the gid, loginsh, oid, shlvl, tcsh,
tty, uid and version shell variables and the HOST,
REMOTEHOST, VENDOR, OSTYPE and MACHTYPE environment
variables.

A new syntax for including useful information in the prompt string
(see prompt).
and special prompts for loops and spelling correction
(see prompt2 and prompt3).

Read-only variables. See Variable substitution.

BUGS

When a suspended command is restarted, the shell prints the directory
it started in if this is different from the current directory. This can
be misleading (i.e., wrong) as the job may have changed directories internally.

When a suspended command is restarted, the shell prints the directory it started in if this is different from the current directory. This can be misleading (i.e., wrong) as the job may have changed directories internally.

Shell builtin functions are not stoppable/restartable. Command sequences
of the form ‘a ; b ; c’ are also not handled gracefully when stopping is
attempted. If you suspend ‘b’, the shell will then immediately execute
‘c’. This is especially noticeable if this expansion results from an
. It suffices to place the sequence of commands in ()’s to force it
to a subshell, i.e., ‘( a ; b ; c )’.

Control over tty output after processes are started is primitive; perhaps
this will inspire someone to work on a good virtual terminal interface.
In a virtual terminal interface much more interesting things could be
done with output control.

Alias substitution is most often used to clumsily simulate shell procedures;
shell procedures should be provided rather than aliases.

Commands within loops are not placed in the history
list. Control structures should be parsed rather than being recognized as
built-in commands. This would allow control commands to be placed anywhere,
to be combined with ‘|’, and to be used with ‘&’ and ‘;’ metasyntax.

doesn’t ignore here documents when looking for its .

It should be possible to use the ‘:’ modifiers on the output of command
substitutions.

The screen update for lines longer than the screen width is very poor
if the terminal cannot move the cursor up (i.e., terminal type ‘dumb’).

HPATH and NOREBIND don’t need to be environment variables.

Glob-patterns which do not use ‘?’, ‘*’ or ‘[]’ or which use ‘{}’ or ‘~’
are not negated correctly.

The single-command form of does output redirection even if
the expression is false and the command is not executed.

includes file identification characters when sorting filenames
and does not handle control characters in filenames well. It cannot be
interrupted.

Command substitution supports multiple commands and conditions, but not
cycles or backward s.

Report bugs at http://bugs.gw.com/, preferably with fixes. If you want to
help maintain and test tcsh, send mail to tcsh-request@mx.gw.com with the
text ‘subscribe tcsh’ on a line by itself in the body.

THE T IN TCSH

In 1964, DEC produced the PDP-6. The PDP-10 was a later re-implementation. It
was re-christened the DECsystem-10 in 1970 or so when DEC brought out the
second model, the KI10.

In 1964, DEC produced the PDP-6. The PDP-10 was a later re-implementation. It was re-christened the DECsystem-10 in 1970 or so when DEC brought out the second model, the KI10.

TENEX was created at Bolt, Beranek & Newman (a Cambridge, Massachusetts
think tank) in
1972 as an experiment in demand-paged virtual memory operating systems. They
built a new pager for the DEC PDP-10 and created the OS to go with it. It was
extremely successful in academia.

In 1975, DEC brought out a new model of the PDP-10, the KL10; they intended to
have only a version of TENEX, which they had licensed from BBN, for the new
box. They called their version TOPS-20 (their capitalization is trademarked).
A lot of TOPS-10 users (‘The OPerating System for PDP-10’) objected; thus DEC
found themselves supporting two incompatible systems on the same hardware–but
then there were 6 on the PDP-11!

TENEX, and TOPS-20 to version 3, had command completion
via a user-code-level subroutine library called ULTCMD. With version 3, DEC
moved all that capability and more into the monitor (‘kernel’ for you Unix
types), accessed by the COMND% JSYS (‘Jump to SYStem’ instruction, the
supervisor call mechanism [are my IBM roots also showing?]).

The creator of tcsh was impressed by this feature and several others of TENEX
and TOPS-20, and created a version of csh which mimicked them.

LIMITATIONS

Words can be no longer than 1024 characters.

Words can be no longer than 1024 characters.

The system limits argument lists to 10240 characters.

The number of arguments to a command which involves filename expansion is
limited to 1/6th the number of characters allowed in an argument list.

Command substitutions may substitute no more characters than are allowed in
an argument list.

To detect looping, the shell restricts the number of
substitutions on a single line to 20.

SEE ALSO

tset(1), vi(1), x(1), access(2), execve(2), fork(2), killpg(2),
pipe(2), setrlimit(2), sigvec(2), stat(2), umask(2), vfork(2), wait(2),
malloc(3), setlocale(3), tty(4), a.out(5), termcap(5), environ(7),

VERSION

This manual documents tcsh 6.14.00 (Astron) 2005-03-25.

AUTHORS

TagDescription

William Joy
 
Original author of (1)

J.E. Kulp, IIASA, Laxenburg, Austria
 
Job control and directory stack features

Ken Greer, HP Labs, 1981
 
File name completion

Mike Ellis, Fairchild, 1983
 
Command name recognition/completion

Paul Placeway, Ohio State CIS Dept., 1983-1993
 
Command line editor, prompt routines, new glob syntax and numerous fixes
and speedups

Karl Kleinpaste, CCI 1983-4
 
Special aliases, directory stack extraction stuff, login/logout watch,
scheduled events, and the idea of the new prompt format

Rayan Zachariassen, University of Toronto, 1984
 
and builtins and numerous bug fixes, modifications
and speedups

Chris Kingsley, Caltech
 
Fast storage allocator routines

Chris Grevstad, TRW, 1987
 
Incorporated 4.3BSD into

Christos S. Zoulas, Cornell U. EE Dept., 1987-94
 
Ports to HPUX, SVR2 and SVR3, a SysV version of getwd.c, SHORT_STRINGS support
and a new version of sh.glob.c

James J Dempsey, BBN, and Paul Placeway, OSU, 1988
 
A/UX port

Daniel Long, NNSC, 1988
 
wordchars

Patrick Wolfe, Kuck and Associates, Inc., 1988
 
mode cleanup

David C Lawrence, Rensselaer Polytechnic Institute, 1989
 
autolist and ambiguous completion listing

Alec Wolman, DEC, 1989
 
Newlines in the prompt

Matt Landau, BBN, 1989
 

Ray Moody, Purdue Physics, 1989
 
Magic space bar history expansion

Mordechai ????, Intel, 1989
 
printprompt() fixes and additions

Kazuhiro Honda, Dept. of Computer Science, Keio University, 1989
 
Automatic spelling correction and prompt3

Per Hedeland, Ellemtel, Sweden, 1990-
 
Various bugfixes, improvements and manual updates

Hans J. Albertsson (Sun Sweden)
 
ampm, and

Michael Bloom
 
Interrupt handling fixes

Michael Fine, Digital Equipment Corp
 
Extended key support

Eric Schnoebelen, Convex, 1990
 
Convex support, lots of bug fixes,
save and restore of directory stack

Ron Flax, Apple, 1990
 
A/UX 2.0 (re)port

Dan Oscarsson, LTH Sweden, 1990
 
NLS support and simulated NLS support for non NLS sites, fixes

Johan Widen, SICS Sweden, 1990
 
shlvl, Mach support, , 8-bit printing

Matt Day, Sanyo Icon, 1990
 
POSIX termio support, SysV limit fixes

Jaap Vermeulen, Sequent, 1990-91
 
Vi mode fixes, expand-line, window change fixes, Symmetry port

Martin Boyer, Institut de recherche d’Hydro-Quebec, 1991
 
autolist beeping options, modified the history search to search for
the whole string from the beginning of the line to the cursor.

Scott Krotz, Motorola, 1991
 
Minix port

David Dawes, Sydney U. Australia, Physics Dept., 1991
 
SVR4 job control fixes

Jose Sousa, Interactive Systems Corp., 1991
 
Extended fixes and delete command

Marc Horowitz, MIT, 1991
 
ANSIfication fixes, new exec hashing code, imake fixes,

Bruce Sterling Woodcock, sterling@netcom.com, 1991-1995
 
ETA and Pyramid port, Makefile and lint fixes, ignoreeof=n addition, and
various other portability changes and bug fixes

Jeff Fink, 1992
 
and

Harry C. Pulley, 1992
 
Coherent port

Andy Phillips, Mullard Space Science Lab U.K., 1992
 
VMS-POSIX port

Beto Appleton, IBM Corp., 1992
 
Walking process group fixes, bug fixes,
POSIX file tests, POSIX SIGHUP

Scott Bolte, Cray Computer Corp., 1992
 
CSOS port

Kaveh R. Ghazi, Rutgers University, 1992
 
Tek, m88k, Titan and Masscomp ports and fixes. Added autoconf support.

Mark Linderman, Cornell University, 1992
 
OS/2 port

Mika Liljeberg, liljeber@kruuna.Helsinki.FI, 1992
 
Linux port

Tim P. Starrin, NASA Langley Research Center Operations, 1993
 
Read-only variables

Dave Schweisguth, Yale University, 1993-4
 
New man page and tcsh.man2html

Larry Schwimmer, Stanford University, 1993
 
AFS and HESIOD patches

Luke Mewburn, RMIT University, 1994-6
 
Enhanced directory printing in prompt,
added ellipsis and rprompt.

Edward Hutchins, Silicon Graphics Inc., 1996
 
Added implicit cd.

Martin Kraemer, 1997
 
Ported to Siemens Nixdorf EBCDIC machine

Amol Deshpande, Microsoft, 1997
 
Ported to WIN32 (Windows/95 and Windows/NT); wrote all the missing library
and message catalog code to interface to Windows.

Taga Nayuta, 1998
 
Color ls additions.

THANKS TO

Bryan Dunlap, Clayton Elwell, Karl Kleinpaste, Bob Manson, Steve Romig,
Diana Smetters, Bob Sutterfield, Mark Verber, Elizabeth Zwicky and all
the other people at Ohio State for suggestions and encouragement
termio(7) , Introduction to the C ShellThis manual documents tcsh 6.14.00 (Astron) 2005-03-25.Bryan Dunlap, Clayton Elwell, Karl Kleinpaste, Bob Manson, Steve Romig, Diana Smetters, Bob Sutterfield, Mark Verber, Elizabeth Zwicky and all the other people at Ohio State for suggestions and encouragement

All the people on the net, for putting up with,
reporting bugs in, and suggesting new additions to each and every version

Richard M. Alderson III, for writing the ‘T in tcsh’ section





  

Advertisements


SCH – Otto (Clip Officiel)


SCH ‘ROOFTOP’ inclut les titres \”R.A.C.\” et \”Ça ira\” , nouvel album disponible ici : https://sch.lnk.to/schrooftopAY

\”Pharmacie\” extrait de l’album \”JVLIVS\”, Disponible maintenant : https://sch.lnk.to/jvlivsTA , inclus \”Pharmacie\” et \”Mort de rire\”.
En concert à l’Olympia Paris le 31 janvier et au Dôme de Marseille le 2 mars. Vos places : http://bit.ly/SchTournee
Instrumental : Katrinasquad

Un film de Late Nights (http://instagram.com/latenights_studio)
Production exécutive Sicile: Beleda
Scénario: Samy Baaroun
Montage : Chill

Retrouvez SCH sur :
https://www.facebook.com/schmathafack
https://instagram.com/sch
https://twitter.com/Sch_Mathafack
Snapchat : sch.zbllh

นอกจากการดูบทความนี้แล้ว คุณยังสามารถดูข้อมูลที่เป็นประโยชน์อื่นๆ อีกมากมายที่เราให้ไว้ที่นี่: ดูความรู้เพิ่มเติมที่นี่

SCH - Otto (Clip Officiel)

Test CSH-5L dò cá 360 độ Cá Cơm


Test CSH-5L dò cá 360 độ Cá Cơm

CON CÁO GIÀ Chim Sẻ và 30 PHÚT THỦ NHÀ TRẦN LỰC trước sức ép NGHẸT THỞ | AoE Highlights


“Chim Sẻ Đi Nắng Official” là kênh Youtube chuyên phát lại các trận đấu trực tiếp của Chim Sẻ Đi Nắng.
Ngoài ra còn kênh: Chim Sẻ Đi Nắng Video (https://www.youtube.com/channel/UCaAGSoGPXGtk8szSfzXCmQ)
Sẽ phát lại đầy đủ tất cả các kèo đấu hàng ngày của Chim Sẻ Đi Nắng!
Xem AOE thả ga free data 3G trên kênh chính thức của SBS với cú pháp:
CS gửi 9062 (gói ngày, 3.000VND/ngày)
CS30 gửi 9062 (gói tháng, 35.000/tháng)
Ủng hộ clan SBS tại:myclip.vn/live/5991/11
► Nội dung video thuộc bản quyền của Chim Sẻ Đi Nắng Studio.

Tham gia cùng cộng đồng Fan của Chim Sẻ Đi Nắng,các bạn vui lòng truy cập:
►FanPage CSDN: https://www.facebook.com/chimsedinangFanpage
►Facebook cá nhân CSDN : https://www.facebook.com/188fl
►Tham gia group CSDN tại : https://bit.ly/csdn_fanclub
►Kênh TikTok chính thức của CSDN : https://www.tiktok.com/@chimsedinang16
►Instagram chính thức của CSDN : https://www.instagram.com/chimsedinan…
►Liên hệ hợp tác
Mobile/Zalo: 096.9376.210
Email: dungntk.csdns@gmail.com

chimsedinang aoe moi nhat 2020 aoe csdn aoehighlight chimse deche sieupham chimsedinangstudio teamaoesbs dechemoi keoaoemoinhat chimsemoinhat trandauaoemoinhat aoe2021 deche2021 aoede aoe2

CON CÁO GIÀ Chim Sẻ và 30 PHÚT THỦ NHÀ TRẦN LỰC trước sức ép NGHẸT THỞ | AoE Highlights

Máy chụp CSH 8L đi nước cạn 12m thấy tín hiệu sắc nét rõ ràng không xước nhiễu dội đáy


Hoàng Channel Nhân viên chuyển giao ứng dụng SĐT: 0707 676 153 (Zalo)

Furuno CSH8L SONAR
Furuno CSH8L là một máy dò ngang quét vòng tròn đầy đủ hiển thị trong một màn hình kích thước nhỏ gọn với phạm vi trong 1600 mét. Nó hoạt động ở tần số 85 kHz, hoạt động tốt cho vùng nước nông và gần thuyền cho thấy cả điều kiện đáy biển và phân bố cá. Góc nghiên Tự động quét là một tính năng tiêu chuẩn của CSH8L.
📝🛍🔎🔍 Sản phẩm bà con có thể tham khảo và đặt mua tại đây: http://haidang.vn/viVN/maydongangsonar204/furunocsh8lmark21213.aspx
🌎 🌍 🌏 Sản phẩm Furuno được bán tại hơn 100 đại lý và đối tác của Hải Đăng trên toàn quốc, là nhà phân phối độc quyền sản phẩm Furuno tại Việt Nam trong lĩnh vực Điện tử hàng hải.
👜👜 Mua sản phẩm, bảo hành sửa chữa đừng quên đến Hải Đăng : http://haidang.vn/
🌟 Đăng ký để xem ngay video mới nhất: ➤ https://www.youtube.com/channel/UCEgBEkKTNeAtPLvxYbGARjA/featured

Máy chụp CSH 8L đi nước cạn 12m thấy tín hiệu sắc nét rõ ràng không xước nhiễu dội đáy

CSH#627 – TIẾNG TRỐNG MÊ LINH – LƯU THANH THỦY – THANH TÂM


Chương trình này được thu hình bởi HỢP NHẤT MEDIA

CSH#627 - TIẾNG TRỐNG MÊ LINH - LƯU THANH THỦY - THANH TÂM

นอกจากการดูบทความนี้แล้ว คุณยังสามารถดูข้อมูลที่เป็นประโยชน์อื่นๆ อีกมากมายที่เราให้ไว้ที่นี่: ดูวิธีอื่นๆGeneral news

ขอบคุณมากสำหรับการดูหัวข้อโพสต์ csh

Leave a Comment