In 1978, a copy of UNIX was given to the Computer Science Department at the University of California at Berkeley. Under a contract from an agency of the United States government, the students and faculty developed the first 32-bit virtual memory version of UNIX. As part of that effort a new command shell, dubbed the C Shell, was written. This new shell provided a number of features that were not available with the Bourne Shell.
The new functionality added to the C Shell was designed to benefit the interactive user. Two important additions were the history mechanism, allowing the user to reuse and modify previously executed commands; and job control, which provided for more control over tasks initiated by the user. A third very visible change made with the C Shell was the new programming language for writing shell programs, or scripts.
The architects of Berkeley UNIX and the C Shell patterned the shell programming language for their new shell after the C programming language. Their aim was to make writing shell programs easy for users, many of whom already were proficient in the C programming language. If you are familiar with the now popular C programming language, you will find writing shell scripts for the C Shell easy, because doing so is much like writing a C program.
As you complete each chapter of this book, you will become more comfortable and proficient with the commands and features of the C Shell. The hallmark features of the C Shell--command history and job control, as well as the C-like programming language--will be important labor savers, and perhaps even sanity savers. When you find that you don't have to retype entire command lines if you've used them just moments before, you will appreciate the history mechanism.
You will learn about C Shell job control at the end of this book. Using job control, you will start a procedure, answer its questions, interrupt it, and put it in the background, freeing up your terminal to do other work while the procedure processes behind the scenes. If the job needs input, it will inform you. You can then bring it back, supply the data or answers, and then return it to the background. On a simple terminal without windowing, this helps you be more productive. Even with windowing, you can do more work with your existing open windows.
Now, back to the question, Why use the C Shell? Well, if anything I have said in the last few paragraphs appeals to you, then you should use the C Shell. None of the features just discussed are a part of the Bourne Shell. There are other shells, available on some UNIX versions, that incorporate some or all of these features in one form or another. The difference between those other shells and the C Shell is that, if you move from one version of UNIX to another, you can't depend on finding those other shells. The two command shells you will find in all versions of UNIX are the Bourne Shell and the C Shell.
There are two easy ways for you to find out which shell has been set up as your default shell. One way is to look in the password file in your account record to see what is in the last field in the record. This always contains the path of the default shell. The password file is /etc/passwd. If you use the UNIX grep command--a text searching program--you won't have to look through the entire password file to locate and display your record. To use grep, you enter the following command (here shown in bold) on your system:
1 % grep David /etc/passwd davide:AQ1#BpsGN&mY:100:20:David Ennis, x5021:/usr/davide:/usr/bin/csh 2 % _
/etc/passwd
in my example.
With no options selected, the default behavior of grep is to display any lines
of text that contain the match pattern. The line of text that follows the grep
command, beginning with davide, is the text that was located in the password
file.The password file contains records, which are lines of text, one for each login account on the system. Each account record contains seven fields delimited with colons (:). The seven fields contain the following information :
davide
).
AQ1#BpsGN&mY
).
100
).
20
).
David Ennis, x5021
).
/usr/davide
).
/usr/bin/csh
).
There is a second method used to determine your default shell setting. When you
log in to the system and your login shell is started, it sets a special shell
variable to the value of your current shell. Variables are the topic of Day 4,
--Shell Variables, Part I" and Day 5, "Shell Variables, Part
II." The specific variable that you are interested in, called$shell
always contains the value of your current shell.
The system looks at the last field in your password record to find your default shell. When you examine $shell from a login shell, the value of your current shell is the same as your default shell setting. The easiest way to look at a shell variable is to use the shell's built-in command echo to display its contents. The echo command and the rest of the C Shell's built-in commands are the topic of Days 8, 9, and 10 of this book. Enter echo $shell on your system to find out the setting of your default shell:
2 % echo $SHELL /usr/bin/csh 3 % _
The
shell echo command displays the contents of the shell variable$shell
. In the
preceding example, you see that mine is set to /usr/bin/csh, which is the same
as what is in my password file record displayed earlier. After you have chosen
and changed your default shell setting, it will not change unless you or your
administrator alters it.
A qualification to this statement has to be made if you are working in a networked environment where you have access to more than one system. It is possible for you to have a different default shell setting on another host that you have access to over the network. This is especially true if the machine is from a different vendor, or if it is administered by a different person, group, or organization. You will want to check those hosts in the same manner and perhaps change your default shell on those hosts, so that you are using the same shell on all systems that you access. This will make using UNIX much easier for you.
The syntax for the chsh
command is
chsh default-shell-path
where
the default-shell-path
is the full file pathname of the command shell program
that you want to use as your default shell. Check with your system
administrator if you cannot locate the shell of your choice.
Example: chsh /usr/bin/csh
When you use the chsh command to change your default shell, it changes the contents of the last field of your password file record to reflect the new shell pathname you entered on the command line. This change stays in effect until the next time you use chsh to change your default to another value. This change is what I like to call temporarily permanent, because it can be modified but is otherwise permanent. Next I will show you how to quickly change your current shell without using chsh. This change is temporary in the true sense of the word.
chsh
to change your default shell setting, be sure
that you properly spell the pathname for your new shell. If you misspell any
part of the pathname and don't catch your error before logging out of the
system, your logon will fail when you attempt to log in the next time. Most
likely, the system will be unable to locate the file that you give to chsh
and
will not be able to start a login shell for you. The only way to fix this is to
contact your administrator and ask to have the pathname corrected in your
password entry. So be careful!To make this temporary change, at your command prompt you simply enter the command name of the new shell you wish to run. If, for example, you find that your default shell is the Bourne Shell, and you want to run the C Shell at this time, enter csh at the command prompt. The next prompt you see will be coming from the C Shell and not from your default Bourne Shell.
$ csh % _
csh [-bcefinstvVxX] [argument...]
The
csh
command has twelve option flags, shown in the square brackets, that affect
the operation of the shell. Some of these options are more appropriate to
either the interactive or noninteractive mode of operation of the shell, but
none are limited to one or the other. Each of the options is explained briefly
here and in more detail where appropriate later in the book.OPTIONS
$argv
, the argument-list shell
variable.
.cshrc
file and, if the shell is a login shell, the .login
file upon startup. This accelerates the startup of the shell.
$verbose
shell variable, enabling echoing
of command input after history substitutions (and before other substitutions) have been made, but
before the command is executed.
$verbose
is set before the shell reads . cshrc
.
$echo
shell variable, enabling echoing of command input after all substitutions have been made.
$echo
is set before the shell reads.cshrc
.Except for -c, -i, -s, and -t, the first argument that is not an option is assumed to be the name of a command or script. This argument is passed as argument zero, the name of the command program. Subsequent arguments are added to the argument list for the command or script.
(-) to the name of the shell to change the name. This acts as a special flag to the login shell so that it can read the .login file if it exists in your home directory.
If you look at the syntax for the csh command, you'll notice that it has many options. You may think that, because the system starts your login shell, you don't have the ability to set any of these options. This is not the case, however. There is a method available by which you can set these options for your login shell if you choose to. Using the special variables, you can set these options either temporarily, for a single session, or permanently, where they will be set every time you log in to the system.
To set an option on temporarily, you can simply set its corresponding shell variable at a command prompt in your login shell, or any other shell. The option remains in effect until it is unset or the current shell session is ended. It is not reinstated for later shell sessions unless you specifically set it again at the command prompt.
For any option that you want to be in effect for all of your interactive shell sessions, the method is basically the same. You set the options by setting the shell variables. The difference is that each time the shell starts, it--rather than you'sets the variables at the command prompt. To do this, you put the commands to set the variables in one of your startup files, .cshrc or .login. You'll learn more about these two files and how they affect the operation of the shell on Day 6.
3 % csh myscript -f -v -b -q -x 4 % _This separation happens by a special arrangement in which the csh command takes the options up to, but not including, the -b option for itself and passes the options after the -b option to the command that it is executing.
4 % csh -c scriptfile -v -a infile1 infile2 5 % _The options and file arguments that follow scriptfile on the command line are put into the $argv argument-list variable for use by the commands within scriptfile. The difference between this example and the one for the -b option is that here only the -c is processed as an argument to the csh command. In the case of scriptfile, it may not otherwise be clear to the C Shell that this file contains commands, so you use the -c option to indicate that fact to the shell. Later, you'll learn methods by which you can specify unambiguously that a file is a shell script, and thus not need this option.
-n option. With this option, the shell will parse and interpret all of the commands in your script but will not execute them. If there are errors in the script, the parsing and interpreting will report them, as it would during a regular execution. Unlike the regular execution of a shell, script processing proceeds to the end of the script regardless of whether errors are encountered and reported.
-v option, the -V option causes the shell to set the verbose shell variable and to echo commands just after history substitutions have been made. The important difference between the two verbose options is that this one, -V, sets the verbose shell variable before the shell starts to read the .cshrc startup file. This allows you to view the processing that the shell performs on your startup file and that could be affecting how your script executes.
The -X option is also not left on scripts that have been debugged; it too produces volumes of output.
% exit Welcome to UNIX Login: _
Another
way to end the C Shell is to enter^D
, that is, to hold down the Control key
while you type the letter D.^D
, also represented as Control-D, is the UNIX
end-of-file (EOF) character, and when the C Shell sees the EOF on input, it
takes that to be the end of the command file and terminates. This can be a
dangerous way to end the shell.
Some UNIX commands can accept input from the terminal rather than from a file
specified on the command line. To indicate to these commands that you are
finished with input, you use the same ^D
EOF character. If you were to
accidentally enter an extra^D
, your shell would end when you least expect it
to end. To avoid this, the C Shell has a special shell variable that acts as a
switch to disable ^D
for exiting the shell. That special variable is
$ignoreeof
, which, as it name implies, tells the shell to ignore the EOF
character.
To find out whether you have this switch set, you can use the set command to
display all of your shell variables and their current settings. See the example
in the next section to see what the output looks like. In that example,
you'll see that there is a line with the word ignoreeof
on it. This
indicates that the $ignoreeof
shell variable is in fact set to ON. If it were
not set to ON, you would not see ignoreeof
in the list displayed by the set
command.
On Day 6, you'll learn more about a special file, .logout
, that you can
use to configure special processing that occurs when you exit from your login
shell and log out of your system.
$history
variable. This shell variable sets the number of commands that the shell keeps
in its history, before discarding the oldest saved command. You can set the
variable to any number, but typically you set it initially to a reasonable
value like 50. Later, as you become more experienced using the C Shell, you
will likely increase this number so that you can keep a bigger backlog of
command history.
First you can check to see if, in fact, you have the $history
variable set.
Your system administrator may have given you a startup file, as part of the
initial configuration of your account, that included a command line to set this
variable for you. To find out whether you already have $history
set, you can
use the C Shell set command to show all of the currently defined variables.
Here is an example:
5 % set argv () cwd /usr/dave history 20 home /usr/dave ignoreeof noclobber path (/bin /usr/bin /usr/dave/bin /usr/lib .) prompt ! % shell /bin/csh status 0 term vt100 6 % _
set
command at your command
prompt will probably be different from what is shown in the example, but in
general this is similar to what you will see. The first column is the name of
the variables that you have set in your current shell session. The second
column is the value that the variable contains. Notice that two of the
variables, ignoreeof
and noclobber
, do not have values. These are special
variables that behave like switches. When they appear in the list they are ON,
and when they are absent from the list they are OFF. These and the other
reserved shell variables are explained in detail during Days 4 and
5. set
command example, notice
that there is a line that begins with history
and has the number 20 after it.
If you see a similar line in the output from your set
command, then you know
that you have the command-history feature enabled for your shell sessions.
Don't worry now about the value set for your $history
variable. If it is
set, the value is likely to be something reasonable and will be adequate for
working the examples that follow. If you choose, you can edit your .cshrc
file
and change the value setting for the $history
variable.
history
, and when entered, it
displays all of the commands in your history list, up to the number set in the
$history
variable. Consider this example:
6 % history 1 grep David /etc/passwd 2 echo $shell 3 csh myscript -f -v -b -q -x 4 csh -c scriptfile -v -a infile1 infile2 5 set 6 history 7 % _When you enter the
history
command at your shell prompt, your output will be
different from what I have shown here but should look similar in format. What
you see is a list of the command history, those commands that you have entered
at the shell prompt since you logged onto the system. Your output may not have
all of the commands that you have entered if the number exceeded the value of
your $history
variable. In that case, you will see only the most recent
commands listed. For example, if your $history
is set to 20, but you have
entered 30 commands since you started on the system, your history list would
start with command number 11 and end with command number 30.The commands contained in your history list are referred to as events. You should have noticed in the last example that each of these events has a number shown next to it in the output from the history command. These numbers are called event numbers and are important because this is how you identify the command in history that you want to reuse and possibly modify. Throughout the remainder of this book, I will use the terms event and event number to refer to command lines in the history list and the number associated with them.
.txt
. You might want to find files like this in several
subdirectories. To do so, you would enter at your command prompt the command in
the following example:
7 % ls *.txt memo.txt test.txt welcome.txt 8 % cd stuff 9 % !7 ls *.txt letter.txt tutorial.txt 10 % _In this example, you see that there were three files in the current directory that end in
.txt
. In event 8, I used the cd command--which you will learn more
about on Day 8, "C Shell Built-In Commands----to change the
current directory to one called stuff
. Event 9 then does something interesting.
It recalls event 7, the ls command, which then displays the two files in
directory stuff
that end in.txt
.
The syntax for the history recall commands is shown here. All of the commands
begin with the exclamation character (!), sometimes called a bang. This
character informs the C shell that what follows refers to a history event.
To recall an event by its event number, use this syntax:
% !event_number
To
recall the last event, use the following syntax:
% !!
To recall an event by a relative event number, use
% !-relative_event_offset
where
the relative_event_offset is subtracted from the current event number to get
the number of the event to be recalled.
To recall an event by text content, use this:
% !text_string_beginning_of_event
or
this:
% !?text_string_contained_in_event[?]
The following sections explain in greater detail how to use these variations on recalling history events.
!7
to recall event number 7. When you recall
history events, the C Shell always first displays the event being recalled. If
you look again at event 9, you see that the ls
command from event 7 is
displayed before it is executed, producing the output shown in the example.
This permits you to verify the command that was executed as a result of the
recall.
Depending on the setting of your $history
variable, you might on occasion try
to recall an event that the shell has discarded. When the number of events
exceeds the value in $history
, the shell discards the oldest command before
adding the newest one to the list. If you reference an event that is no longer
in the history list, the shell returns the command prompt with no action taken.
!!
at the command prompt.
(-) and the number of events back that you want to recall. If you want to
recall the command three events ago, you would enter !-3:
10 % !-3 ls *.txt memo.txt test.txt welcome.txt 11 % _
Do
the simple arithmetic to find that the current event (10) minus 3 is equal to
7, which is the original ls command that looked for files ending in.txt
. The
event recalled is echoed as always and then executed, producing the output
listing all of the files that match.
$history
variable to, say, 100, it will become more challenging
for you to remember the event number of some command that you did an hour ago
and now want to repeat. For just this situation, the C Shell has yet another
way to recall events.
Instead of following the bang with an event number, you can follow the bang
with the name of the command that you want to recall. The shell searches
backwards from the most recent event until it finds a match. That event is then
displayed and executed. The one restriction is that the text must match exactly
to the beginning of the command line originally entered. For example, to recall
by text the echo command from event 2 (see earlier in this chapter), you would
use!echo
:
11 %!echo echo $shell /bin/csh 12 % _
The
shell searches backwards through the history list until it finds an event that
starts with echo. If it does find a match, it displays the event and then
executes the command. In event 11, I recalled the most recent event that began
with the string echo
. The shell displayed the command, echo $shell
, and then
performed the command, producing the output /usr/bin/csh
.
Because this method only matches to the initial characters of an event, it is
not always easy for you to use to recall the specific event you have in mind.
So the C Shell provides an alternate way to match an event using text rather
than an event number. In this method, as in the last, you use the bang and the
text you want to match, but between the bang and the text, you put a question
mark(?)
. This tells the shell that you want to match the most recent event
that contains the text anywhere in the event string. Perhaps
you have done more ls commands since the one you are interested in recalling,
but they had
different match strings than the one you want. You can recall an older event by
matching to a string within the event, instead of strictly at the beginning.
You would do so by using a command like that shown in the following example:
12 % !?myscript csh myscript -f -v -b -q -x 13 % _
In
this example, I recalled event 3 from earlier in the chapter by matching to the
string myscript. If I had tried to match to the beginning of the line with
!csh
, I would have recalled event 4 instead, because it was the more recent
event that matched to csh at the start of the command. With this method, I was
recall the event I wanted by matching to text contained within the event.
Optionally, you can follow the match text by another question mark(?). This is required only when you want to follow the match text with new text to be appended to the recalled event. The additional question mark is then needed to tell the C Shell where the match text ends and the appended text starts:
13 % !?myscript? appended_filename csh myscript -f -v -b -q -x appended_filename 14 % _
Here
I recalled the same event as before, but I also added a filename,
appended_filename
, to the end of the command as part of the action of recalling
the event.
Table 1.1 lists the C Shell word designators and a brief description of what each one indicates when used in recalling an event for modification.
Designator Description # The entire command line entered up to this point. 0 The first input word (the command). n The nth argument on the command line. ^ The first argument on the command line (that is, 1). $ The last argument on the command line. x--y The range of words from word x to word y. -y The range from 0-y. * All of the arguments, or a null value if just one word is in the event (that is, just a command). x* Abbreviates x-$. x- Like x* but omits word $.
14 % ls testfile.txt testfile.txt 15 % cat !$ This is the text that was in a file "testfile.txt-- in my home directory /usr/dave. I will use this file in examples where I want to look at text in a file. 16 % _
In
this example, I first did an ls
command to see that the file testfile.txt
exists. The ls
command displayed the filename, showing that the file is
present. Then I included the same filename, testfile.txt
, in the next command,
which I entered by using the history word designator !$
in place of a filename
with the command cat. The shell made the substitution of the last word from the
previous command onto this command line, and the result was to display the
contents of the file on my terminal.
You could also just as easily use the word modifier !^
to indicate that the
first argument in the previous command should be substituted. In the last
example, because there is only one argument, the first and last argument are
the same, so the result would be identical. In all cases, history word
modifiers must be prefixed with the bang character to indicate that a history
reference follows.
In the last example, using just the bang(!)
, I referenced the most recent
event. If you need to reference an earlier event, you have to further qualify
the modifier in the command. If you want to use the ls command on the files
that were referenced in event 13, you could use the following command:
16 % ls !13:$ !13:^ ls appended_filename myscript appended_filename myscript 17 % _In this example, I substituted the last argument word and the first argument word on the
ls
command. The shell echoed back the resulting command after the
substitution and then it executed the command. The filenames that appear,
appended_filename
and myscript
, are the results displayed by the ls
command.
Once again, there is a another way I could have done the last example and still
have received the same results. Rather than using the event number in the
substitution, I could have used one of the forms of text recall, as I did in
the simpler examples earlier in this section. Then, in place of the event
number!13
, I could have used either !csh
to match on the command name or
either !?myscript
or !?appended_filename
to match to text within event 13.
Lastly, you can use one of the word range designators to include some portion of the arguments from a previous event in your current command. I will leave that to you as an exercise to experiment with independently as you explore the possibilities of history substitutions and event modification.
You learned about the two modes of operation of the shell: the interactive mode, in which you receive command prompts from the shell at your terminal; and the noninteractive mode, in which the shell is processing a script file that contains C Shell and UNIX commands. Ways to end the C Shell were also demonstrated, and the options for starting up the C Shell were presented with brief explanations.
The last part of Day 1 introduced the C Shell's command history facility. You were shown a number of methods for recalling events from history and how to modify those recalled events. I also presented the event word designators that enable you to use selected words from previous events in a new command.
In Day 2, "Metacharacters," you will learn about shell metacharacters, which are used in filename generation, pattern matching, input and output modification, and much more. This material will be the foundation upon which your effective use of the C Shell will be based.
Consult Appendix E at the end of this book for examples of the
--dot" files".cshrc, .login
, and.logout
. You can modify these
files to customize your shell environment. Doing so is covered in Day
6.
Other Shells:
Look in Section 1 of your UNIX manuals for the man pages
for the more
and pg
commands. Determine which of these commands is available on
your system, and learn more about the different capabilities of these versatile
commands.
A The C Shell has a history facility, by which you can recall command lines that were previously executed. You can then repeat those command lines or modify them and execute the modified version. Additionally, the C Shell provides a job control capability that gives you the ability to exert more control over your background processes. This feature is covered in the last chapter of the book.
Q What is the command that I would use to change my default shell? Where is the C Shell usually found on UNIX systems?
A The command used to change your default shell is chsh
. To use this
command, you give it a single argument, which is the pathname of the shell that
you want to have as your new default. On some systems, the C shell is in
/bin/csh
, whereas on others you will find it in /usr/bin/csh
. Typically, if
your system is Berkeley-kernel based, the first path applies. On the other
hand, if yours is a System V-based kernel system, look for the C Shell in
/usr/bin/csh
.
Q How can I quickly repeat the last command that I entered?
A The quick way to do that is with the history recall of!!
. All history
substitutions begin with the exclamation, or bang, character(!)
, and the
second exclamation mark is a short hand for the previous command.
Q How can I make a quick change of one word of the last command and rerun it?
A The Quick Substitution character is the carat(^)
. Enclose first the
string you want to change in carats, followed by the string to replace it with,
and a closing carat (for example,^change_this^to_that^
). The first occurrence
of the search string will then be replaced by the second, and the resulting
command line will then be executed.