[rfc791.ORG]
Bill Joy (right), inventor of the C Shell gives props to one of the men that made it possible, Dennis Ritchie, who designed the C programming language and was pretty heavily involved in the creation of the original Unix.

[ rfc791.ORG : Unix Help : C Shell ]

csh - history, file completion, and job-control aware shell
csh was written by Bill Joy, a grad student at the University of California at Berkeley in the mid 1970's. csh is a shell - the program that starts right after you log in and interprets your subsequent commands.
Shells usually expect you to type the name of a program file followed by a list of parameters which tell the program what to do.
rm myfile.html
Typing this in, for example, tells the shell to run the `rm' command, and to pass in `myfile.html' as a parameter. The `rm' command interprets it's one parameter as the name of a file to remove, and it removes `myfile.html'.
kill -HUP 943
This tells the shell to execute the `kill' program, passing `-HUP' and `943' as parameters. The `kill' program interprets it's first parameter as a signal to send to a process, and the second parameter as a the ID of the process to send the signal to. The `kill' program then sends a HUP signal to Process ID 943.

Like most other shells, csh has Filename Globbing (this allows you to operate on multiple files whose names match a pattern without typing all their names), and Pipes and Redirection (the ability to take the output of one program as the input of another, or a file, etc) . Additionally it has job control (the ability to switch easily between tasks, suspend jobs, resume jobs, etc), command history (a log of recent commands you've typed and a mechanism to reenter the commands, possibly with modifications, with minimal effort), filename completion (the ability for you to press a key and have the shell finish typing a filename for you, assuming you've typed in enough to make the filename unique). Csh also has the huge advantage of being written in the 70's, so pretty much any unix system you run across today will have it or some variant (tcsh is one example).

Filename Globbing

Filename globbing is something the shell does to convert each command line you type. It converts command line arguments which contain special wildcard characters into lists of files that match a pattern. Possible wildcard characters are the question mark (?), which is interpreted as single character, and the asterisk (*), which is interpreted as any number of characters.
rm *
In the example above, before the shell runs the rm command, it converts the asterisk(*) into a list of all the files in the current directory. The rm command then deletes all the files specified as parameters (all of them, because the shell globbed the asterisk, see?).
rm *.jpg
rm /var/log/*
These commands remove all files ending in `.jpg' and all files in `/var/log', respectively.
rm file?.gif
This will remove file1.gif and filea.gif, but not file12.gif (because we only put one question mark in our glob).

If we want a program to actually see a question mark or an asterisk (or a number of other special characters) in it's parameter list, we can `quote' them a number of ways. These three examples would all remove a file named `*.txt'.
As a side note, this is how it is that you can have a file under Unix called `*.txt', but cannot have a file by that name under DOS. The DOS command interpreter doesn't do filename globbing at all, so DOS programs have to be written to handle globbing themselves. If you're curious about how this affects Samba, click here.



Doug McIlroy, then head of the research department at BTL where Unix was developed, bugged Ken Thompson to include a facility in Unix that allowed "coupling programs like garden hose," or taking the output of one program as the input of another. When Ken finally agreed, the pipe (|) was born.

Pipes and redirection

Every process in Unix has a standard input and a standard output. Standard input (or as many C unix programmers will refer to it `stdin') usually comes from the keyboard, and standard output (`stdout') usually goes to the terminal screen. Pretty much every shell, however, allows you to connect the stdin or stdout of a program you run to a variety of things. You can dump the stdout of a process into a file, you can `pipe' it into the stdin of another process, you can have a program take its stdin from a file. This allows plugging a whole set of tools into each other. The pipes and redirection facility described below is availiable in Bourne, Korn, and Bourne Again shells in addition to C Shell. This facility was also (somewhat) stolen by DOS. You can also put the stdout of a command on the command line for another command with backticks (`). Processes all have a Standard Error (stderr) in addition to their Standard Output where they can put output also. Standard Error is not buffered like Standard Output, so messages processes output to stderr show up on the terminal immediately. Standard Error is thus used frequently to output error messages (thus it's name).
The standard redirection operator (>), and the standard pipe operator (|) only operate on Standard Output. If you want to redirect both stdout and stderr, use >&.
nslookup rfc791.ORG >& nslookup.rfc791.txt
To pipe both stdout and stderr, use |&
find . -name "*.mp3" |& less

Command History

It's possible to get csh to rerun a command you'd typed previously. Each command you type gets a history number. Monolith and Dylan have their csh prompts set up initially to show you the history number in square brackets. You can rerun a command as is by typing a bang (!) followed by the history number.

Dylan[49]% who 
brad     ttyp0    Oct 16 05:17  (Monolith)
Dylan[50]% date
Wed Oct 16 05:17:26 EDT 2002
Dylan[51]% !49
who
brad     ttyp0    Oct 16 05:17  (Monolith)
Dylan[52]%
You can also run a command you typed a given number of commands ago by typing a bang, a hyphen, then however many commands ago the desired command was.

Dylan[49]% who
brad     ttyp0    Oct 16 05:17  (Monolith)
Dylan[50]% date
Wed Oct 16 05:17:26 EDT 2002
Dylan[51]% !-2
who
brad     ttyp0    Oct 16 05:17  (Monolith)
Dylan[52]%
The last command you typed (!-1) can be quickly summoned by a double-bang.
Dylan[52]% who 
brad     ttyp0    Oct 16 05:17  (Monolith)
Dylan[53]% !!
who
brad     ttyp0    Oct 16 05:17  (Monolith)
Dylan[54]% 
The command line arguments are available by using a colon followed by an argument number.
!-2:3
This gives argument three to the command 2 commands ago.
!!:0 
This gives just the command name of the last command.
!54:*
This gives all the arguments, with the exception of the command name, of command 54.

You can also modify commands before they are rerun.
!-4:s/usr/home/
This substitues the word `home' for the word `usr' in the command four commands ago.
^myfile^yourfile^
This replaces the word `myfile' with the word `yourfile' in the last command.

You can see what a command from the history would look like without running it by adding :p.
!!:p
This prints the entire last command you typed, but doesn't run anything.
!-4:s/maine/vermont/:p
This substitutes the word `maine' in the command four commands ago with the word `vermont' and prints out what the resulting command would look like without running it.

Adding :p to the end of a history command does not preclude the resulting command from being included in the history.
Dylan[61]% fole `which cah`
cah: Command not found.
fole: Command not found.
Dylan[62]% !!:s/cah/csh/:p
fole `which csh`
Dylan[63]% !!:s/fole/file/
file `which csh`
/bin/csh: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for NetBSD, statically linked, stripped
Dylan[64]%
Here I wanted to run `which csh' (which finds and prints the full path to csh, and file (which takes the path to a file and prints it's file type. Note I'm using backticks again.
However I biffed. I mistyped both `file' and `csh'. So on command 62, I replaced cah with csh, and in command 63, I replaced fole with file, and ran the new command.
The resulting command tells us that /bin/csh (there's that full path) is a 32-bit little-endian program for NetBSD/i386 .
This trick is handy for trying a history command to check what it looks like first, and then really running it afterwards.
Dylan[64]% !!:p
file `which csh`
Dylan[65]% !!:s/csh/sh/:p
file `which sh`
Dylan[66]% !!
file `which sh`
/bin/sh: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for NetBSD, statically linked, stripped
Dylan[67]% 
If a chunk of text you want to replace exists multiple times in a previous command line, and you don't want to replace just the first one, you need to do a global substitution with `g':
Dylan[68]% mv jpg1.jpg jpg2.jpg jpg3.jpg jpgs
Dylan[69]% !!:gs/jpg/gif/
mv gif1.gif gif2.gif gif3.gif gifs
Dylan[70]%
Regular expresions can also be used in substitutions.

A neat feature to also be aware of - if you know the first few letters of the command you typed -- enough to make it unique in your history -- then you can use a bang followed by that. This was really handy for me the other day when I was editing some source code, compiling it and testing it over and over:
Tethys[51]% vi audio.java
Tethys[52]% javac audio.java
Tethys[53]% appletviewer audio.html
Tethys[54]% !vi
Tethys[55]% !ja
Tethys[56]% !ap
Tethys[57]% !vi
Tethys[58]% !ja
Tethys[59]% !ap

Filename Completion

Filename completion is a simple facility in which the shell can type the rest of a filename in for you. Many, many Unix commands take filenames as command-line parameters, so this comes in handy often.
First you need to make sure that the shell variable named `filec' is set. Monolith and Dylan do this for you when you log in, but most systems don't. I won't fully explain what that means here, but I'll show you how to do it, as it's quite simple:
Monolith[101]% set filec
Monolith[102]%
Now the shell will listen for you to press the [ESC] key or hold down the [CTRL] key and hit [D]. When you press [CTRL]+[D], the shell will give you a list of all the files that start with what you've typed. If there's only one possibility, you can hit [ESC] to tell the shell to complete the command line for you.
Monolith[102]% cat .c
before I hit enter on the command line above, I'll hit the [ESC] key.
Monolith[102]% cat .cshrc
if $?prompt then
  set filec
  set history=100
  set savehist=100
  if (${TERM} == "ansi") then
    setenv TERM vt100
  endif
  eval `tset -s`
  mesg y
endif
The shell found the one file in the directory whose name starts with .c, and completed the command line for me. Then it ran cat on the completed filename when I hit enter.
Monolith[103]% cat m
Without hitting enter here, I'll hold the [CTRL] key and hit [D].
Monolith[103]% cat m
mail/ mbox
Monolith[103]% cat m
And I'll type in one more letter to make it a bit more specific
Monolith[103]% cat mb
And now I'll hit [ESC]
Monolith[103]% cat mbox
...
Monolith[104]%

Job Control

Job control is available in bash and ksh as well as csh, and works pretty much identically in all shells involved, as far as I am aware. Job control allows you to run multiple programs and switch between them easily.
Putting a job in the background when you first run it is easy. All you have to do is type an ampersand (&) after your command line.
find / -name "nsswitch.conf" &
The program running in the background is still attached to your terminal, however. This means that any output it produces will still be output to your terminal, wherever your cursor happens to be at the time. This can be irritating, and can cause you to miss the output is it occurs in the middle of a screen refresh. So, we're going to use the facility I talked about way back at the beginning of this document, redirection.
find / -name "nsswitch.conf" >& find.output &
Processes can be switched from foreground to background with the `fg' and `bg' commands. A process in the foreground must be suspended prior to being put into the background. Most programs suspend when you hold down the [CTRL] key and hit Z.
Monolith[103]% find / -name "*.mp3" >& mp3list.txt
^Z
Suspended
Monolith[104]%
A suspended program will not actually be allocated any processor cycles until you put it into the background (with bg) or back into the foreground (with fg).
Monolith[104]% bg
[1]    find / -name *.mp3 >& mp3list.txt &
Monolith[105]%
A list of all the jobs you have both running and suspended, complete with their job numbers can be summoned with the `jobs' command.
Monolith[105]% jobs
[1]  + Running              find / -name *.mp3 >& mp3list.txt
Monolith[106]%
When you have more than one job, you can specify which job you want bg or fg to background or foreground by specifying one of these job numbers as a parameter preceeded by a percent symbol (%).
Monolith[106]% fg %1
[1]    find / -name *.mp3 >& mp3list.txt &
Be aware that a job number is not the same thing as a process ID.
One handy thing about job control is that a job running in the background that you've redirected any output from can continue running happily even after you log out. Suspended jobs and foreground jobs cannot usually do this. If you try to log out while you have suspended jobs, a job-control aware shell will warn you. You can try to logout again, which will cause all background jobs to be killed and you'll then be successfully logged out. If you want the jobs to continue running after you log out instead of being killed, use bg.