|
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.
|
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.
rm "*.txt"
Enclose the parameter in double-quotes (")
rm '*.txt'
Enclose the parameter in single-quotes (')
rm \*.txt
Precede the globbable character with a backslash (\)
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.