C shell

From Seo Wiki - Search Engine Optimization and Programming Languages

Jump to: navigation, search
csh
File:TcshAndShScreenCapture.png
tcsh and sh side-by-side on a Mac OS X desktop.
Original author(s) Bill Joy
Initial release 1978 (1978)
Stable release tcsh 6.17.00 / July 10, 2009; 145253468 ago
Written in C
Operating system BSD, UNIX, Linux, Mac OS X
Type Unix Shell
License BSD license

The C shell (csh or the improved version, tcsh, on most machines) is a Unix shell that was created by Bill Joy while a graduate student at University of California, Berkeley in the late 1970s. It has been distributed widely, beginning with the 2BSD release of the BSD Unix system that Joy began distributing 1978.[1][2] Other early contributors to the ideas or the code were Michael Ubell, Eric Allman, Mike O'Brien and Jim Kulp.[3]

The C shell is a command processor that's typically run in a text window, allowing the user to type commands which cause actions. The C shell can also read commands from a file, called a script. Like all Unix shells, it supports piping, here documents, command substitution, variables, control structures for condition-testing and looping and filename wildcarding. What differentiated the C shell, especially in the 1980s, were its interactive features and overall style. Its new features made it easier and faster to use. And the overall style of the language looked more like C and was seen as more readable.

Today, csh on virtually all machines is actually tcsh, an improved version of csh. As a practical matter, tcsh is csh: One file containing the tcsh executable has links to it as both "csh" and "tcsh" so that either name refers to the same improved version of the C shell.

tcsh added filename and command completion and command line editing concepts borrowed from the Tenex system, which is where the "t" came from. Because it only added functionality and didn't change what was there, tcsh remained backward compatible[4] with the original C shell. And though it started as a side branch from the original source tree Joy had created, tcsh is now the main branch for active ongoing development. tcsh is very stable but new releases continue to appear roughly once a year, consisting mostly of minor bug fixes.[5]

Contents

Design Objectives and Features

The main design objectives for the C shell were that it should look more like the C programming language and that it should be better for interactive use.

More like C

The Unix system had been written almost exclusively in C, so the first objective was a command language that was more stylistically consistent with the rest of the system. The keywords, the use of parentheses and the C shell's built-in expression grammar and its support for arrays were all strongly influenced by C.

By today's standards, csh may not seem particularly more C-like than many other popular scripting languages. But through the 80s and 90s, the difference was seen as striking, particularly when compared to sh, the then-dominant shell written by Stephen Bourne at AT&T. This example illustrates the C shell's more conventional expression operators and syntax.


Template:Columns


At the time, sh lacked an expression grammar. The square bracketed condition had to be evaluated by the slower means of running the external test program. sh's if command took its argument words as a new command to be run as a child process. If the child exited with a zero return code, sh would look for a then clause and run that nested block, otherwise it would run the else. Hard-linking the test program as both "test" and "[" gave the notational advantage of the square brackets and the appearance of the functionality of test being part of the sh language. sh's use of a reversed keyword to mark the end of a control block was a style borrowed from ALGOL 68.[6]

By contrast, csh could evaluate the expression directly, which made it faster. It also claimed better readability: Its expressions used a grammar and a set of operators mostly copied from C, none of its keywords were reversed and the overall style was also more like C.

Here is a second example, comparing scripts that calculate the first 10 powers of 2.


Template:Columns


Again because of the lack of an expression grammar, the sh script uses command substitution and the expr command. The @ statement in C shell is a pun: it's the "at-sign-ment" statement.

Finally, here's a third example, showing the differing styles for a switch statement.


Template:Columns


In the sh script, ";;" marks the end of each case. That's distinguished because sh disallows null statements otherwise.

Improvements for interactive use

The second objective was that the C shell should be better for interactive use. In support of that, it introduced numerous new features that made it easier, faster and more friendly to use by someone sitting at a terminal, typing commands. Users could get things done with a lot fewer keystrokes and it ran faster. The most significant of these new features were the history and editing mechanisms, aliases, directory stacks, tilde notation, cdpath, job control and path hashing. These new features proved very popular and many of them have since been copied by other Unix shells.

History 
Allowed users to recall previous commands and rerun them by typing only a few quick keystrokes. For example, two exclamation marks, "!!", typed as a command and referred to as "bang, bang," meant run the immediately preceding command. Other short keystroke combinations, e.g., "!$" to mean just the last argument of the previous command, allowed bits and pieces of previous commands to be pasted together and edited to form a new command.
Editing Operators 
Editing could be done not only the text of a previous command, but also on variables and allowed a range of operations from simple string search/replace to parsing a pathname to extract a specific segment.
Aliases 
Allowed the user to type the name of an alias and have the C shell expand it internally into whatever set of words the user had defined. For many simple situations, e.g., running the "fgrep" command by typing "f", this ran faster and was more convenient than creating a script.
Directory stack 
Allowed the user to push or pop the current working directory, making it easier to jump back and forth between two different places in the filesystem without having to do much typing.
Tilde notation 
Offered a shorthand way of specifying pathnames relative to the home directory using the "~" character.
Cdpath 
Extended the notion of a search path to the cd (change directory) command: If the specified directory wasn't in the current directory, csh would try to find it in the cdpath directories.
Job control 
Addressed the problem that most users of the day had only simple character-mode terminals. Under sh, a user could only do one thing at a time. A user who started to edit a file had to finish or at least save his work and get out before doing anything else. A user couldn't simply open another window. The C shell's job control solved that by allowing the user the suspend the current activity and create a new instance of the C shell, called a job, by typing ^Z. The user could then switch back-and-forth between jobs using the fg<code> command. The active job was said to be in the foreground. Other jobs were said to be either suspended (stopped) or running in the background.
Path hashing 
Sped up the C shell's search for executable files. Rather than doing filesystem calls in each path directory, one-at-a-time, until it either found the file or ran out of possibilities, the C shell consulted an internal hash table built by scanning the path directories. That table could usually tell the C shell where to find the file, if it existed, without having to search.

Overview of the Language

Basic Statements

The C shells operates line-at-a-time. A basic statement is a sets of words separated by spaces or other characters with special meaning, including parentheses, the piping and i/o redirection operators and the semicolon or ampersand. The first word is taken as name of the command to be run and may be either an internal command, e.g., "<code>echo," or an external command. The rest of the words are passed as arguments to the command.

Commands can be joined on the same line.

";" means run the first command and then the next.
"&&" means run the first command and, if it succeeds with a 0 return code, run the next.
"||" means run the first command and, if it fails with a non-zero return code, run the next.

Normally, when the C shell starts a command, it waits for the command to finish before giving the user another prompt signaling that a new command can be typed. But if there's an "&" at the end of the line, the command will start in the background and csh comes back immediately, ready for a new command.

Wildcarding

If a word contains wildcard characters, it's taken as a pattern and replaced by list of all the filenames that match.

"*" matches any number of characters
"?" matches any single character
"[...]" matches any of the characters inside the square brackets. Ranges are allowed, using the hyphen. If the first character was "!," any character not in the set was matched.

The C shell also introduced several notational conveniences, since copied by other Unix shells.

"abc{def,ghi}" expands as "abcdef" and "abcghi."
"~" means the current user's home directory.
"~user" means user's home directory.

I/O Redirection

By default, when csh runs a command, the command inherits the csh's stdio file handles for stdin, stdout and stderr, which normally all point to window where the C shell is running. The i/o redirection operators allow the command to be run with input and output going to a file.

"> file" means stdout will be written to file. Errors still come to the shell window.
">& file" means both stdout and stderr will be written to file.
"< file" means stdin will be read from file.

Piping

It's also possible to connect commands together using pipes, which causes the output of one command to fed into the input of the next. Both commands run concurrently.

"|" means connect stdout to the stdin of the next command. Errors still come to the shell window.
"|&" means connect both stdout and stderr to the stdin of the next command.

Commmand Substitution

Command substitution takes the output of one command and pastes it back on the command line of another command.

Variables

Control Structures

The C shell provides control structures for both condition-testing and iteration.

Condition-testing

The condition-testing control structures are the if statement and the switch statement.

if Statement

There are two forms of the if statement. The short form is typed on a single line and but can specify only a single command if the expression is true.

if ( <expression ) <command>

The long form used "then", "else" and "endif" keywords to allow for blocks of commands to be nested inside the condition.

if ( <expression1> ) then
   <commands>
else if ( <expression2> ) then
   <commands>
...
else
   <commands>
endif
switch statement

The switch statement compares a string against a list of patterns, which may contain wildcard characters. If nothing matches, the default action, if there is one, is taken.

switch ( <string> )
case <pattern1>:
   <commands>
   breaksw
case <pattern2>:
   <commands>
   breaksw
...
default:
   <commands>
   breaksw
endsw


Iteration

The C shell provides two forms of iteration, the while statement and the foreach.

while statement

The while statement evaluates an expression. If it's true, it runs the nested commands and then repeats.

while ( <expression> )
   <commands>
end
foreach statement

The foreach statement takes a list of values, usually a list of filenames produced by wildcarding, and then for each, sets the loop-variable to that value and runs the nested commands.

foreach <loop-variable> ( <list-of-values> )
   <commands>
end

Expressions Operators

Editing Operators

History

Criticism

Though popular for interactive use because of its many innovative features, csh has never been as popular for scripting. Initially, and through the 1980s, csh couldn't be guaranteed to be present on all Unix systems. sh could, which made it a better choice for any scripts that might have to run on other machines. By the mid-1990s, csh was widely available, but the use of csh for scripting faced new criticism[7][8] over the C shell's alleged defects in the syntax, missing features and poor implementation.

Syntax defects were generally simple but unnecessary inconsistencies in the definition of the language. For example, the set, setenv and alias commands all did basically the same thing, namely, associate a name with a string or set of words. But all three had slight, but completely unnecessary differences. An equal sign was required for a set but not for setenv or alias; parentheses were required around a word list for a set but not for setenv and alias, etc.

The missing feature most commonly cited is the lack of ability to manipulate the stdio file handles independently.

The implementation, which used an ad hoc parser, has drawn the most serious criticism. By the early 1970s, compiler technology was sufficiently mature[9] that most new language implementations used either a top-down or bottom-up parser capable of recognizing a fully recursive grammar. It's not known why an ad hoc design was chosen instead for the C shell. It may be simply that, as Joy put it in an interview in 2009, "When I started doing this stuff with Unix, I wasn't a very good programmer."[10] But that choice of an ad hoc design meant that the C shell language was not fully recursive. There was a limit to how complex a command it could handle.

It worked for most things users typed interactively, but didn't work well and could easily fail, producing only a cryptic error message or an unwelcome result on the more complex commands a user might take time to write in a script. For example, the C shell could not support piping between control structures. Attempting to pipe the output of a foreach command into grep simply didn't work.

Another example is the unwelcome behavior in the following fragments:

  if ( ! -e myfile ) echo mytext > myfile
 
  if ( ! -e myfile ) then
     echo mytext > myfile
  endif

Both of these appear to mean, "If 'myfile' does not exist, create it by writing 'mytext' into it." But the first example creates only an empty file, as the line is parsed such that the file existence is not tested until after the output redirect has been set up.

The implementation is also criticized for its notoriously poor error messages, e.g., "0 event not found", which yields no information about what the problem is.

See also

Further reading

  • Anderson, Gail; Paul Anderson (1986). The UNIX C Shell Field Guide. Prentice-Hall. ISBN 0-13-937468-X. 
  • Wang, Paul (1988). An Introduction to Berkeley UNIX. Wadsworth Pub. Co.. ISBN 0-534-08862-7. 
  • DuBois, Paul (1995). Using csh & tcsh. O'Reilly & Associates. ISBN 1-56592-132-1. 
  • Arick, Martin R. (1993). UNIX C Shell Desk Reference. John Wiley & Sons. ISBN 0471556807. 

References

  1. Harley Hahn, Harley Hahn's Guide to Unix and Linux.
  2. Berkeley Engineering Lab Notes, Volume 1, Issue 2, October 2001.
  3. An Introduction to the C shell by Bill Joy.
  4. tcsh(1) man page
  5. Fixes file in tcsh-6.17.00.
  6. Re: Late Bloomers Revisited USENET post to comp.lang.misc by Piercarlo "Peter" Grandi, Dept of CS, UCW Aberystwyth, UK, Dec 17, 1989.
  7. Csh Programming Considered Harmful by Tom Christiansen
  8. Top Ten Reasons not to use the C shell by Bruce Barnett
  9. David Gries (1971). Compiler Construction for Digital Computers. John Wiley & Sons. ISBN 0-471-32776-X.
  10. Bill Joy in Conversation with Brent Schlender, Churchill Club, Santa Clara, CA, Feb 11, 2009.

External links

Personal tools

Served in 0.563 secs.