Поиск в интернет-магазине Bolero
<Каталог сайтов - Найдётся всё yandex-rambler.ru Приглашение!
Искать на Озоне

Ozon.ru Ozon.ru

Поиск в интернет-магазине Bolero
Назад в будущее


Ch 12 -- The C Shell


TOC BACK FORWARD HOME

UNIX Unleashed, System Administrator's Edition

- 12 -

The C Shell

by John Valley and Sean Drew

As a UNIX user, you have a wide variety of shells available to you: the Bourne shell, Bourne Again shell, POSIX shell, C shell, TC shell, Z shell, and Korn shell. Although this is not an all encompassing list of available shells, it does cover the more commonly used shells. Most UNIX systems come pre-installed with some subset of the shells mentioned. If you wish to use a shell that was not pre-installed on your system, you will more than likely find the one you want on the Internet. The C shell--the subject of this chapter--is one of the more popular and widely available shells in UNIX. It was developed after the Bourne shell but before the Korn shell. The C shell incorporates many features of the Bourne shell and adds many new ones that make your UNIX sessions more efficient and convenient.

Each shell has certain advantages and disadvantages. You might want to review Chapter 13, "Shell Comparison," to help you decide which one to use.

The C shell, written by Bill Joy (also the author of the vi text editor), was not patterned after the Bourne shell. Bill chose the C programming language as a syntax model. The C shell commands--especially if, while, and the other structured programming statements--are somewhat similar in syntax to the equivalent statements in C. A shell is quite a different animal from a compiler, though, so the C programming language served only as a model; many forms and structures in the C shell have nothing to do with the C programming language.

Because the C shell is not just an extension of the Bourne shell syntax, this chapter will cover all aspects of C shell operation. You therefore can read it independently of Chapter 9, "The Bourne Shell," Chapter 10, "The Bourne Again Shell," and Chapter 11, "The Korn Shell."

Invoking the C Shell

Each time you log onto UNIX, you're placed in an interactive shell referred to as your logon shell. If your logon shell is using the default prompts, you can tell if your logon shell is the C shell by its command-line prompt: the percent sign (%). The default C shell prompt differs from the default dollar-sign prompt ($) of the Bourne shell to remind you that you're using the C shell. You can customize your command-line prompt when using the C shell; for more information, see the definition of prompt in "Variables," later in this chapter.

The most foolproof way to determine your logon shell is to query the passwd file. The seventh field contains the path to your logon shell. The command

grep 'whoami' /etc/passwd |cut -f7 -d: 

will print the path of your logon shell. If you are using Network Information Service (NIS) to manage user information, the /etc/passwd file is not accessible, so the command

ypcat passwd |grep 'whoami' |cut -f7 -d: 

will do the trick.

If your logon shell is not the C shell, and the C shell is available on your system, you can invoke it as an interactive shell from the command-line. Even when you're already running the C shell, there will be times when you want to launch the C shell again--for example, to run a shell script or to temporarily change the shell's options. To invoke the C shell interactively, use this command:

$ csh % 


NOTE: The csh command usually is located in the /bin or /usr/bin directory. Because both directories are usually in your search path, you shouldn't have any trouble finding the csh command if your system has it. If you don't find it right away, you might look in the directory /usr/ucb (the standard home for BSD components in a UNIX System V system) or in /usr/local/bin. /usr/local/bin is a home for programs your site has acquired that were not provided with the original system software. Remember that, for many years, the C shell was available only to those sites using the BSD variant of UNIX; unlike the Bourne shell, there is no guarantee that you will have the csh command on your system.

The csh command also supports a number of options and arguments (described later in this chapter in "Shell Options"), but most options are not relevant to running an interactive shell.

Whenever csh is invoked, whether as the logon shell or as a subshell, it loads and executes a profile script named .cshrc. If it is a logon shell, the C shell also executes a profile script on startup named .login and another on exit named .logout. Note that the .login script is executed after .cshrc--not before. For additional information about C shell profile scripts, see "Customizing Your Shell Environment," later in this chapter.

Most versions of the C shell import environment variables such as PATH into local array variables at startup. The C shell does not refer to the public environment variables (including PATH) for its own operation. This means that you'll usually want to maintain the path variable for directory searches--not PATH. Some versions of the C shell do not properly import environment variables, which can give you confusing results. If it appears that you have no search path set, but the PATH variable is set and accurate (as shown by echo $PATH), check that the variable path has a matching value. If not, you'll need to import critical environment variables into local variables yourself.


NOTE: If you are familiar with the Bourne shell, you won't notice much difference when working with the C shell unless you use advanced shell features such as variables, command replacement, and so on.
Important differences do exist, however. Among these are the set of punctuation characters that have a special meaning to the shell (often called metacharacters). The C shell is sensitive to all the special characters of the Bourne shell, as well as the tilde (~), the commercial at sign (@), and the exclamation point (!). Don't forget to quote or escape these characters when writing commands unless you intend to use their special shell meaning. (See "Quoting and Escaping from Special Characters," later in this chapter, for a discussion of the details.)

Shell Basics

When you enter commands at the shell prompt, you are providing input to the shell. The shell sees a line of input as a string of characters terminated with a newline character; the newline is usually the result of pressing Enter on your keyboard. Input to the C shell can be anything from a single, simple command to multiple commands joined with command operators. Each command line you enter is actually a shell statement. In addition to providing input to the shell manually by entering shell statements on the command line, you can provide input to the shell by putting shell statements into a file and executing the file. Files of shell statements commonly are known as shell scripts.

This section covers the basics of interacting with the shell by entering shell statements on the command line. (Of course, anything you can enter on the command line also can be put into a file for later, "canned" execution.) The subsection "Shell Statements: A Closer Look," provides a more detailed, technical look at the components of shell statements. If you plan to write shell scripts, you'll definitely want to read this section.

When you finish this section, you will feel like you know a good deal about the C shell, but this is really just the beginning. In addition to the C shell's basic service of providing a means to instruct the computer, the C shell also provides a number of tools you can use to expedite your work flow. These tools or features of the shell are described in subsequent sections of this chapter.

Executing Commands: The Basics

The C shell accepts several types of commands as input: UNIX commands, built-in shell commands, user-written commands, and command aliases. This section describes the types of commands you can execute and the ways you can execute them.

Command Names as Shell Input A command is executed by entering the command's name on the command-line. The C shell supports any of the following as command names:

  • Built-in C shell command. The shell provides a number of commands implemented within the shell program. When you invoke a built-in command, it therefore executes very quickly because no program files need to be loaded. A built-in command is always invoked by a simple name--never by a pathname (for example, never by /usr/bin/command).

  • Because the shell first checks a command name for built-in commands before searching for a file of the same name, you cannot redefine a built-in command with a shell script. You can use aliases, however, to redirect a built-in command to a shell script. The next subsection, "Built-In Shell Commands," briefly describes each built-in command. Detailed descriptions of built-in commands with examples are presented in the task-oriented sections of this chapter.

  • Filename. You can specify the filename (% filename), a relative pathname (% ../filename), or an absolute pathname (% /bin/filename) of a file as a command. The file must be marked as executable and must be a binary load file or a shell script in the C shell language. Additionally, if pathnames are not used, the file must exist in one of the directories listed in your path shell variable. The C shell cannot process shell scripts written for the other shells unless your UNIX variant supports the #! notation for specifying the correct command processor. (See "Shell Programming," later in this chapter, for notes about using shell scripts with the C shell.)

  • All UNIX commands are provided as executable files in the /bin or /usr/bin directory. A UNIX command generally is invoked by entering its filename or full pathname.

  • Command alias. A command alias is a name you define by using the alias built-in shell command.

  • An alias can have the same name as a built-in shell command or an executable file. You always can invoke an executable file that has the same name as an alias by using the file's full pathname. An alias that has the same name as a built-in command effectively hides the built-in command, however. Aliases are described in detail in "Aliases," later in this chapter.

Built-In Shell Commands C shell provides a number of commands implemented within the shell program. Built-in commands execute very quickly, because no external program file needs to be loaded. Table 12.1 lists the built-in C shell commands. The remainder of this chapter groups these commands into subsections dedicated to particular tasks you'll perform in the shell and describes how to use each command.

Table 12.1. Built-in C shell commands.

Command Description
alias Defines or lists a command alias
bg Switches a job to background execution
break Breaks out of a loop
breaksw Exits from a switch statement
case Begins a case in switch
cd Changes directory
chdir Changes directory
continue Begins the next loop iteration immediately
default Specifies the default case in switch
dirs Lists the directory stack
echo Echoes arguments to standard output
eval Rescans a line for substitutions
exec Replaces the current process with a new process
exit Exits from the current shell
fg Switches a job to foreground execution
foreach Specifies a looping control statement
glob Echoes arguments to standard output
goto Alters the order of command execution
hashstat Prints hash table statistics
history Lists the command history
if Specifies conditional execution
jobs Lists active jobs
kill Signals a process
limit Respecifies maximum resource limits
login Invokes the system logon procedure
logout Exits from a logon shell
newgrp Changes your Group ID
nice Controls background process dispatch priority
nohup Prevents termination on logout
notify Requests notification of background job status changes
onintr Processes an interrupt within a shell script
popd Returns to a previous directory
pushd Changes directory with pushdown stack
rehash Rehashes the directory search path
repeat Executes a command repeatedly
set Displays or changes a shell variable
setenv Sets environment variable
shift Shifts parameters
source Interprets a script in the current shell
stop Stops a background job
suspend Stops the current shell
switch Specifies conditional execution
time Times a command
umask Displays or sets the process file-creation mask
unalias Deletes a command alias
unhash Disables use of the hash table
unlimit Cancels a previous limit command
unset Deletes shell variables
unsetenv Deletes environment variables
wait Waits for background jobs to finish
while Specifies a looping control
%job Specifies foreground execution
@ Specifies expression evaluation

Executing Simple Commands The most common form of input to the shell is the simple command, where a command name is followed by any number of arguments. In the following command line, for example, ftp is the command and hostname is the argument:

% ftp hostname 

It is the responsibility of the command, not the shell, to interpret the arguments. Many commands, but certainly not all, take this form:

% command -options filenames 

Although the shell does not interpret the arguments of the command, the shell does interpret some of the input line before passing the arguments to the command. Special characters entered on a command line tell the shell to redirect input and output, start a different command, search the directories for filename patterns, substitute variable data, and substitute the output of other commands.

Entering Multiple Commands on One Line Ordinarily, the shell interprets the first word of command input as the command name and the rest of the input as arguments to that command. The semicolon (;) directs the shell to interpret the word following the symbol as a new command, with the rest of the input as arguments to the new command. For example, the command line

% echo "<h1>" ; getTitle; echo "</h1>" 

is the equivalent of

% echo "<h1>" % getTitle % echo "</h1>" 

except that, in the second case, the results of each command appear between the command input lines.

When the semicolon is used to separate commands on a line, the commands are executed in sequence. The shell waits until one command is complete before executing the next command. You also can execute commands simultaneously (see "Executing Commands in the Background," later in this chapter) or execute them conditionally, which means that the shell executes the next command if the command's return status matches the condition (see "Executing Commands Conditionally," later in this chapter).

Entering Commands Too Long for One Line Command lines can get quite lengthy. Editing and printing scripts is easier if command lines are less than 80 characters, the standard terminal width. Entering commands that span multiple lines is accomplished by escaping the newline character, as in the following command, which translates some common HTML sequences back to a readable format:

% sed -e "s/%3A/:/" -e "s@%2F@/@g" -e "s@%3C@<@g" \ -e 's/%5C/\\/g' -e "s/%23/#/g" -e "s/%28/(/g" \ -e "s/%29/)/g" -e "s/%27/'/g" -e 's/%22/\"/g' infile > outfile 

The shell sees a line of input as a statement terminated with a newline character; however, the newline character also is considered to be a white-space character. If you end a line with a backslash (\), the next character--the newline character--is treated literally, which means that the shell does not interpret the newline character as the end of the line of input.

Executing Commands in the Background Normally, when you execute commands, they are executed in the foreground. This means that the C shell will not process any other commands, and you cannot do anything else until the command finishes executing. If waiting for long commands to complete is not in your top 10 list of things to do, you can have your current shell handle more commands without waiting for a command to finish. You can execute the command in the background by putting an ampersand (&) at the end of the command:

% find . -name "*.c" -print & [2] 13802 % 

You also can run multiple commands in the background simultaneously:

% xterm & xclock & xload & 

A command executing in the background is referred to as a job, and each job is assigned a job number--the bracketed number in the previous example. The C shell provides you with several commands for managing background jobs; see "Job Control," later in this chapter, for more information.

Repeatedly Executing a Command: repeat You can use the repeat command to execute some other command a specified number of times. Although the repeat command isn't used frequently, it can be quite handy on occasion. If you are writing a shell script to print a document, for example, you might use the command

repeat 5 echo ################################ 

to mark its first page clearly as the start of the document.

The syntax of the repeat command follows:

repeat count command 

For count, specify a decimal integer number. A count of zero is valid and suppresses execution of the command.

For command, specify a simple command that is subject to the same restrictions as the first format of the if statement. The command is scanned for variable, command, and history substitutions; filename patterns; and quoting. It cannot be a compound command (foo;bar), a pipeline (foo|bar), a statement group (using {}), or a parenthesized command list ( (foo;bar|bas) ).

Any I/O redirections are performed only once, regardless of the value of count. For example,

repeat 10 echo Hello >hello.list 

results in 10 lines of Hello in a file named hello.list.

Executing Commands in a Subshell: () A command (or a list of commands separated by semicolons) enclosed in parentheses groups the command or commands for execution in a subshell. A subshell is a secondary invocation of the shell, so any change to shell variables, the current directory, or other such process information lasts only while executing the commands in the subshell. This is a handy way, for example, to switch to another directory, execute a command or two, and then switch back without having to restore your current directory:

% (cd /usr/local/etc/httpd/htdocs; cp *.html /users/dylan/docs) 

Without the parentheses, you would have to write this:

% cd /usr/local/etc/httpd/htdocs % cp *.html /users/dylan/docs % cd /previous/directory 

The syntax for grouping commands follows:

( commands ) 

Enclosing a list of commands in parentheses is a way to override the default precedence rules for the &&, ||, and | operators, at the expense of invoking a subshell and losing any environmental effects of the commands' execution. For example, (grep || echo) | pr pipes the output of the grep command, and possibly that of echo if grep sets a nonzero exit code, to the pr command.

I/O redirections can be appended to the subshell just as for a simple command; the redirections are in effect for all the commands within the subshell. For example,

(cat; echo; date) > out 

writes the output of the cat, echo, and date commands to a file named out without any breaks. If you look at the file afterward, first you'll see the lines written by cat, followed by the lines written by echo, and finally the lines written by date. Similarly, input redirections apply to all commands in the subshell, so that each command in turn reads lines from the redirected file, starting with the line following those read by any previously executed commands in the subshell.

Executing Commands Conditionally Compound commands are actually two or more commands combined so that the shell executes all of them before prompting for (or, in the case of shell scripts, reading) more input.

Compound commands are not often needed for interactive work. Compound commands form a very useful extension to the C shell's syntax, however, especially in shell scripts. Some compound command formats, such as & (background job) and | (the pipe operator) are essential to work effectively with UNIX.

Conditional Execution on Success: && (And) You use the double ampersand operator (read and) to join two commands: command1 && command2. It causes the shell to execute command2 only if command1 is successful (that is, command1 has an exit code of zero).

For command1 or command2, you can write a simple command or a compound command. The && operator has higher precedence than || but lower precedence than |. For example,

grep mailto *.html | pr && echo OK 

echoes OK only if the pipeline grep | pr sets a zero exit code. (For pipelines, the exit code is the exit code of the last command in the pipeline.)

The compound command

tar cvf docs.tar docs && rm -rf docs 

shows one possible benefit of using &&: The rm command deletes the docs directory only if it first is backed up successfully in a tar file.

Conditional Execution on Failure: || (Or) You use the or operator to join two commands: command1 || command2. It causes the shell to execute command2 only if command1 failed (that is, returned a nonzero exit code).

For command1 or command2, you can write a simple command or a compound command. The || operator has lower precedence than both the && and | operators. For example, in the following command

grep mailto *.html || echo No mailto found | pr 

either grep succeeds and its output is placed to standard output, or the words No mailto found are piped to the pr command.

Use the || operator to provide an alternative action. In the following case, if the mkdir command fails, the exit command prevents further execution of the shell script:

mkdir $tmpfile || exit 

Shell Statements: A Closer Look

A command is a basic command or a basic command embellished with one or more I/O redirections.

A basic command is a series of words, each subject to replacements by the C shell, which, when fully resolved, specifies an action to be executed and provides zero or more options and arguments to modify or control the action taken. The first word of a basic command, sometimes called the command name, must specify the required action.

In plainer terms, a statement is the smallest executable unit. When the shell is operating in interactive mode, it displays its prompt when it requires a statement. You must continue to enter shell statement components, using multiple lines if necessary, until you complete a full statement. If the statement is not completed on one line, the shell continues to prompt you, without executing the line or lines you have entered, until it receives a full statement.

Shell statements are formed from a number of tokens. A token is a basic syntactic element and can be any of the following:

  • Comments. A comment begins with any word having a pound sign (#) as its first character and extends to the end of the line. This interpretation can be avoided by enclosing the pound sign (or the entire word) in quotes. (See "Quoting and Escaping Special Characters," later in this chapter.) The # is considered a comment for non-interactive C shell sessions only.

  • White space. White space consists of blanks and tabs, and sometimes the newline character. White space is used to separate other tokens which, if run together, would lose their separate identity. Units of text separated by white space are generically called words.

  • Statement delimiters. Statement delimiters include the semicolon (;) and the newline character (generated when you press Return). You can use the semicolon to place commands together on the same line. The shell treats the commands as if they had been entered on separate lines.

  • Normally, every command or shell statement ends at the end of the line. The Return (or Enter) key you press to end the line generates a character distinct from printable characters, blanks, and tabs, which the shell sees as a newline character. Some statements require more than one line of input, such as the if and while commands. The syntax description for these commands shows how they should be split over lines; the line boundaries must be observed, and you must end each line at the indicated place, or you will get a syntax error.

  • Operators. An operator is a special character, or a combination of special characters, to which the shell attaches special syntactic significance. Operators shown as a combination of special characters must be written without white space between them, or they will be seen as two single operators instead of a two-character operator. For example, the increment operator ++ cannot be written as + +.

  • Punctuation characters that have special significance to the shell must be enclosed in quotes to avoid their special interpretation. For example, the command grep '(' *.cc uses quotes to hide the right parenthesis from the shell so that the right parenthesis can be passed to grep as an argument. See "Quoting and Escaping from Special Characters," later in this chapter, for details about using quotes.

  • Words. A word is any consecutive sequence of characters occurring between white space, statement delimiters, or operators. A word can be a single group of ordinary characters, a quoted string, a variable reference, a command substitution, a history substitution, or a filename pattern; it also can be any combination of these elements. The final form of the word is the result of all substitutions and replacements, together with all ordinary characters, run together to form a single string. The string then is used as the command name or command argument during command execution.

Filename Substitutions (Globbing)

Filename generation using patterns is an important facility of the Bourne shell. The C shell supports the filename patterns of the Bourne shell and adds the use of {} (braces) to allow greater flexibility. Globbing also is known as wildcarding.

Several shell commands and contexts allow the use of pattern-matching strings, such as the case statement of switch and the =~ and !~ expression operators. In these cases, pattern strings are formed using the same rules as for filename generation, except that the patterns are matched to another string.

When any of the pattern expressions described in Table 12.2 are used as arguments of a command, the entire pattern string is replaced with the filenames or pathnames that match the pattern. By default, the shell searches the current directory for matching filenames, but if the pattern string contains slashes (/), it searches the specified directory or directories instead. Note that several directories can be searched for matching files in a single pattern string: a pattern of the form dir/*/*.cc searches all the directories contained in dir for files ending with .cc.

Table 12.2. Pattern expressions.

Expression Definition
* The asterisk, also known as a star or splat, matches any string of characters, including a null string (the asterisk matches zero or more characters). When the asterisk is used by itself, it matches all filenames. When the asterisk is used at the beginning of a pattern string, leading prefixes of the filename pattern are ignored: *.cc matches any filename ending with .cc. When the asterisk is used at the end of a pattern string, trailing suffixes of the filename pattern are ignored: foo* matches foo.cc, foobar.html, and any filename beginning with foo. An asterisk in the middle of a pattern means that matching filenames must begin and end as shown but can contain any character sequences in the middle: pay*.cc matches filenames beginning with pay and ending with .cc, such as payroll.cc, paymast.cc, and paycheck.cc. Multiple asterisks can be used in a pattern: *s* matches any filename containing an s, such as sean.txt or apps.hh.
? The question mark matches any one character. For example, ? as a complete word matches all filenames one character long in the current directory. The pattern pay?.cc matches pay1.cc and pay2.cc but not payroll.cc. Multiple question marks can be used to indicate a specific number of don't-care positions in the filename: pay.?? matches filenames beginning with pay. and ending in any two characters, such as pay.cc and pay.hh, but does not match pay.o.
[] The square brackets enclose a list of characters. Matching filenames contain one of the indicated characters in the corresponding position of the filename. For example, [abc]* matches any filename beginning with the letter a, b, or c. Because of the asterisk, the first character can be followed by any sequence of characters.
Use a hyphen (-) to indicate a range of characters. For example, pay[1-3].c matches filenames pay1.cc, pay2.cc, and pay3.cc, but not pay4.cc or pay11.cc. Multiple ranges can be used in a single bracketed list. For example, [A-Za-z0-9]* matches any filename beginning with a letter or a digit. To match a hyphen, list the hyphen at the beginning or end of the character list: [-abc] or [abc-] matches an a, b, c, or hyphen.
~ The tilde (~) can be used at the beginning of a word to invoke directory substitution of your home directory. The (~) is substituted with the full pathname of your home directory. Also used in the form ~/path to refer to a file or directory under your home directory. If the tilde does not appear by itself as a word and is not followed by a letter or a slash, or it appears in any position other than the first, it is not replaced with the user's home directory. Thus, /usr/rothse/file.cc~ is a reference to the file file.cc~ in the directory /usr/rothse.
~name Substituted with the full pathname of user name's home directory. For example, ~ken/bin refers to /usr/ken/bin if the home directory for user ken is /usr/ken. The password file /etc/passwd is searched for name to determine the directory pathname; if name is not found, the shell generates an error message and stops.
{} Braces enclose a list of patterns separated by commas. The brace expression matches filenames having any one of the listed patterns in the corresponding position of the name. For example, the pattern
/usr/home/{kookla,fran,ollie}/.cshrc
expands to the path list
/usr/home/kookla/.cshrc /usr/home/fran/.cshrc /usr/home/ollie/.cshrc
Unlike *, ?, and [], brace-enclosed lists are not matched against existing filenames; they simply are expanded into words subject to further substitution regardless of whether the corresponding files exist. Brace-enclosed lists can be nested--for example, /usr/{bin,lib,home/{john,bill}} refers to any of the directories /usr/bin, /usr/lib, /usr/home/john, and /usr/home/bill.

It is important to realize that filename generation using pattern strings can cause a replacement of one word with many. A filename pattern must be a single word. The ordinary characters and pattern-matching characters in the word describe a rule for choosing filenames from the current or specified directory. The word is replaced with each filename or pathname found that matches the pattern. If you had three files in your current directory (ch1.txt, ch2.txt and chlast.txt), then the pattern *.txt would expand to match those three files:

% echo Files: *.txt Files: ch1.txt ch2.txt chlast.txt 

You can use pattern expansion in many ways; for example, the expansion below is used to set a shell variable to be an array of three items. The array is then queried for its length and second element. See "Using Array Variables" later in this chapter, for more information about C shell arrays.

 % set files=(*.txt) % echo Found $#files files Found 3 files % echo $files[2] ch2.txt 


TIP: Another powerful C shell feature for determining files in a directory is the command/filename viewing feature that uses control D (Ctrl-D). This feature enables you to determine the files available for a command without aborting the command. For example, if you type cp ~sdrew/docs/ind and want to see which files match the specification, pressing Ctrl-D displays a list of matching files in a multicolumn format. Certain files have a character appended to indicate the file type (this behavior is similar to the output of ls -F): executables are marked with an asterisk (*), directories are marked with a slash (/), and links are marked with an at sign (@). After the column-sorted list is displayed, the command is redisplayed so that you can continue typing. The files listed will be those that match the pattern ~sdrew/docs/ind*. Note that ~(Ctrl-D) prints a list of all users who have accounts on the system.
Commands can be completed in a similar manner if the C shell is expecting a command as part of your current input. The current command pattern is looked for in each directory specified in the PATH environment variable. Note that aliases are not expanded by Ctrl-D. If my PATH is set to /bin:~/bin:/usr/bin and I complete the command pri using Ctrl-D, the output is roughly the same as ls /bin/pri* ~/bin/pri* /usr/bin/pri*.
In addition to getting lists of commands and filenames, the Escape (ESC) key can be used to complete partially typed commands and filenames. The automatic completions are known as command completion and filename completion, depending on whether you are completing a filename or a command. The pattern matching is done as in the Ctrl-D viewing utility. If the partial name is unique, the name is completed; otherwise, the terminal bell is sounded. If ambiguities are encountered (that is, more than one file matches), the name is completed to the ambiguity, and the terminal bell is sounded. Suppose you had two files in a directory named veryLongName.txt and veryLong_Name.txt and you wanted to edit the file veryLong_Name.txt, you can save yourself a great deal of typing by using filename completion. You can type vi ve(Esc), which completes to vi veryLong and rings the bell. Then, if you type _(Esc), the name completes to vi veryLong_Name.txt, at which point you can press Enter and begin your vi session.

Redirecting Input and Output

The C shell provides several commands for redirecting the input and output of commands. You might be familiar with the input (<) or output (>) redirection characters from earlier chapters. The C shell provides you with these and more.

An I/O redirection is an instruction to the shell you append to a command. It causes one of the standard file descriptors to be assigned to a specific file. You might have encountered standard files in the discussion of the Bourne shell in Chapter 9. The UNIX operating system defines three standard file descriptors: standard input (stdin), standard output (stdin), and standard error (stderr).


NOTE: The UNIX operating system actually provides at least 25 file descriptors for use by a command. It is only by convention that the first three are set aside for reading input, writing output, and printing error messages. Unless you instruct otherwise, the shell always opens these three file descriptors before executing a command and assigns them all to your terminal.

A file descriptor is not the file itself; it is a channel, much like the audio jack on the back of your stereo--you can connect it to any audio source you want. Similarly, a file descriptor such as standard input must be connected to a file--your terminal by default, or the disk file or readable device of your choice.

You can change the location where a command reads data, writes output, and prints error messages by using one or more of the I/O redirection operators. Table 12.3 lists the operators.

Table 12.3. I/O redirection operators.

Format Effect

Input Redirection

< filename Uses the contents of filename as input to a command.
<< word Provides shell input lines as command input. Lines of the shell input that follow the line containing this redirection operator are read and saved by the shell in a temporary file. Reading stops when the shell finds a line beginning with word. The saved lines then become the input to the command. The lines read and saved are effectively deleted from the shell input and are not executed as commands; they are "eaten" by the << operator. Shell execution continues with the line following the line beginning with word. If you use the << operator on a command you type at the terminal, be careful: Lines you type afterward are gobbled up by the shell--not executed--until you enter a line beginning with whatever you specified as word. The << operator most often is used in shell scripts. This technique is known as providing a here document.

Output Redirection

> filename

Writes command output to filename.

>! filename

Writes command output to filename and ignores the noclobber option. The noclobber option is fully explained in "Using Predefined Variables," later in this chapter. Briefly, noclobber causes the shell to disallow the > filename redirection when filename already exists; noclobber is therefore a safety you can use to prevent accidentally destroying an existing file. Sometimes, you will want to redirect output to a file even though it already exists. In such a case, you must use the >! operator to tell the shell you really want to proceed with the redirection. If you don't set the noclobber option, you don't need to use the >! operator.

>& filename

Writes both the command output and error messages to filename.

>&! filename

Writes both the command output and error messages to filename and ignores the noclobber option.

>> filename

Writes command output at the end of filename (Append mode).

>>! filename

Writes command output at the end of filename (Append mode) and ignores the noclobber option.

>>& filename

Writes command output and error messages at the end of filename (Append mode).

>>&! filename

Writes command output and error messages at the end of the filename (Append mode) and ignores the noclobber option.

In Table 12.3, filename represents any ordinary filename or pathname; or any filename or pathname resulting after variable substitution, command substitution, or filename generation.

I/O redirection operators are appended to a command; for example, date >curdate writes the current date to the file curdate instead of to your terminal. You also can use more than one redirection per command: Simply list them one after another at the end of the command. The order doesn't matter: for example, both cat <infile >outfile and cat >outfile <infile have the same effect.

Input Redirection Some commands make no special use of the standard input file, such as the date and the ls system commands; others require an input file to function properly, such as the cat and awk commands. You can use the < redirection operator in the form command < filename to designate a file as the source of input for commands such as cat and awk; if you do not, these commands read data from your keyboard--sometimes useful, but usually not. If you provide an input redirection, but the command does not read data (such as ls), the I/O redirection still is performed by the shell; it is just ignored by the command. Note that it is an error to redirect standard input to a file that doesn't exist.

The redirection << word is a special form of the input-redirection operator. Instead of taking input from a file, input to the command comes from the current shell input stream--your keyboard, if you append << to a command you type in, or your shell script if you use << on a command in a shell script.

For word, you choose an arbitrary string to delimit the lines of input. Then write the lines to be provided to the command as input immediately following the command line, and follow the last line of desired input with a line beginning with word. The shell reads the lines up to word, stores the lines in a temporary file, and sets up the temporary file as standard input for the command.

The << word form of input redirection is called a here document, because it is located here, in line with your shell commands. Here documents are useful when you want to provide predefined data to a command, and they save you from having to create a file to hold the data.

Unlike the filename part of other I/O redirection operators, word for the here document is not scanned for variable references, command substitutions, or filename patterns; it is used as is. All the following shell input lines are checked for the presence of word as the only word on the line before any substitutions or replacements are performed on the line.

Normally, lines of the here document are checked for variable references and command replacements; this enables you to encode variable information in the here document. If you quote any part of word, however, the lines are read and passed to the command without modification. The redirection << STOP reads lines up to STOP and performs substitutions on the lines it reads, for example. The redirection << "STOP" reads lines up to the line beginning with STOP and passes the lines directly to the command, as they are, without substitutions or replacements of any kind.

The line beginning with word is discarded; it is not passed to the command in the here document or executed by the shell.

The following example shows the use of a here document to create an HTML form:

cat <<HERE <FORM method=post action=http://host.com/cgi-bin/addTime.sh> <select NAME=username> ´´./doUserQuery;./parseList.sh users_$$.txt "$userName"´´ </select> <input type=submit value=Submit> </form> HERE 

The line containing the word HERE will not appear in the output; it is simply a mark to let the shell know where the redirected lines end.

Output Redirection Output redirections have the general form > filename and >> filename. The first operator creates a new file of the specified filename. The file is opened before command execution begins, so even if the command fails or cannot be found, or if the shell finds an error on the command line and stops, the output file still is created.


NOTE: For purposes of understanding shell syntax, you should note that appending an I/O redirection to a simple command yields a simple command. Except where specifically prohibited, a command with redirections appended can be used wherever a simple command is allowed, such as on the single-line if statement.

If you've set the noclobber option (with set noclobber), the shell refuses to create the named output file if it already exists; doing so would destroy the file's current contents. If you want to perform the output redirection even if the file filename already exists, use the redirection operator >! instead; it overrides the noclobber option.

The >> command arranges for command output to be added to the end of the named file. For this redirection operator, the noclobber option requires that the named file already exist. If you use the alternative form >>!, or if you use >> and the noclobber option is not set, the shell creates the named file if necessary.

The >& and >>& operators redirect both the standard output and standard error files to filename. The Bourne shell enables you to redirect the standard output and standard error files separately; the C shell does not.


TIP: Although the C shell offers no direct means for redirecting standard error and standard output at the same time, you can achieve the net result at the expense of a subshell. In the subshell, redirect standard output via the > operator to the desired location for non-error messages and then redirect standard error and standard output from the subshell via the >& operator to the desired location for error messages. Because the standard output was redirected in the subshell, the standard output and standard error redirection from the subshell will contain only the standard error.
Suppose that you want to run a script, buildSystem, that builds a large software class library and generates nearly 1MB of output, of which a few messages might be errors. The following command places standard output in a file named build.log and error messages from standard error in buildErr.log:
 
% (buildSystem -version 5.1 > build.log) >& buildErr.log
 

Quoting or Escaping from Special Characters

As you saw in previous sections, certain characters have special meanings for the shell. When the shell encounters a special character, the shell performs the action defined by the special character. The following punctuation characters available on the standard keyboard are special to the shell and disrupt the scanning of ordinary words:

~ ' ! @ # $ % ^ & * ( ) \ | { } [ ] ; ' " < > ?