Assignment statement

 < Day Day Up > 

Although some of the functionality of tcsh is present in bash, differences arise in the syntax of some commands. For example, the tcsh assignment statement has the following syntax:

 set variable = value 

Having SPACEs on either side of the equal sign, although illegal in bash, is allowed in tcsh. By convention shell variables in tcsh are generally named with lowercase letters, not uppercase (you can use either). If you reference an undeclared variable (one that has had no value assigned to it), tcsh will give you an error message, whereas bash will not. Finally the default tcsh prompt is a greater than sign (>), but it is frequently set to a single $ character followed by a SPACE. The examples in this chapter use a prompt of tcsh $ to avoid confusion with the bash prompt.

tip: Do not use tcsh as a programming language

If you have used UNIX and are comfortable with the C or TC Shell, you may want to use tcsh as your login shell. However, you may find that the TC Shell is not as good a programming language as bash. If you are going to learn only one shell programming language, learn bash. The Bourne Again Shell is used throughout Linux to program many system administration scripts.

Shell Scripts

With tcsh you can execute files containing TC Shell commands, just as bash can execute files containing Bourne Again Shell commands. The concepts of writing and executing scripts in the two shells are similar. However, the methods of declaring and assigning values to variables and the syntax of control structures are different.

You can run bash and tcsh scripts while using any one of the shells as a command interpreter. Various methods exist for selecting the shell that runs a script. Refer to "#! Specifies a Shell" on page 265 for more information.

If the first character of a shell script is a pound sign (#) and the following character is not an exclamation point (!), the TC Shell executes the script under tcsh. If the first character is anything other than #, tcsh calls the sh link to bash to execute the script.

tip: echo: getting rid of the RETURN

The tcsh echo builtin accepts either a n option or a trailing \c to get rid of the RETURN that echo normally displays at the end of a line. The bash echo builtin accepts only the n option (refer to "read: Accepts User Input" on page 487).

tip: Shell game

When you are working with an interactive TC Shell, if you run a script in which # is not the first character of the script and you call the script directly (without preceding its name with tcsh), tcsh calls the sh link to bash to run the script. The following script was written to be run under tcsh but, when called from a tcsh command line, is executed by bash. The set builtin (page 484) works differently under bash and tcsh. As a result the following example (from page 361) issues a prompt but does not wait for you to respond:

 tcsh $ cat user_in echo -n "Enter input: " set input_line = "$<" echo $input_line tcsh $ user_in Enter input: 

Although in each case the examples are run from a tcsh command line, the following one calls tcsh explicitly so that tcsh executes the script and it runs correctly.

 tcsh $ tcsh user_in Enter input: here is some input here is some input 

Entering and Leaving the TC Shell


You can execute tcsh by giving the command tcsh. If you are not sure which shell you are using, use the ps utility to find out. It shows whether you are running tcsh, bash, sh (linked to bash), or possibly another shell. The finger command followed by your username displays the name of your login shell, which is stored in the /etc/passwd file. If you want to use tcsh as a matter of course, you can use the chsh (change shell) utility to change your login shell:

 bash $ chsh Changing shell for sam. Password: New shell [/bin/bash]: /bin/tcsh Shell changed. bash $ 

The shell you specify will be in effect for your next login and all subsequent logins until you specify a different login shell. The /etc/passwd file stores the name of your login shell.

You can leave tcsh in several ways. The approach you choose depends on two factors: whether the shell variable ignoreeof is set and whether you are using the shell that you logged in on (your login shell) or another shell that you created after you logged in. If you are not sure how to exit from tcsh, press CONTROL-D on a line by itself with no leading SPACEs, just as you would to terminate standard input to another program. You will either exit or receive instructions on how to exit. If you have not set ignoreeof (page 366) and it has not been set for you in a startup file, you can exit from any shell by using CONTROL-D (the same procedure you use to exit from the Bourne Again Shell).

When ignoreeof is set, CONTROL-D does not work. The ignoreeof variable causes the shell to display a message telling you how to exit. You can always exit from tcsh by giving an exit command. A logout command allows you to exit from your login shell only.

Startup Files

When you log in on the TC Shell, it automatically executes various startup files. These files are normally executed in the order described in this section, but you can compile tcsh so that it uses a different order. You must have read access to a startup file to execute the commands in it.

/etc/csh.cshrc and /etc/csh.login

The shell first executes the commands in /etc/csh.cshrc and /etc/csh.login. Superuser can set up these files to establish systemwide default characteristics for tcsh users. They contain systemwide configuration information, such as the default path, the location to check for mail, and so on.

.tcshrc and .cshrc

Next the shell looks for ~/.tcshrc or, if it does not exist, ~/.cshrc (~/ is shorthand for your home directory). You can use these files to establish variables and parameters that are local to your shell. Each time you create a new shell, tcsh reinitializes these variables for the new shell. The following .tcshrc file sets several shell variables, establishes two aliases (page 347), and adds two new directories to path one at the start of the list and one at the end:

 tcsh $ cat ~/.tcshrc set noclobber set dunique set ignoreeof set history=256 set path = (~/bin $path /usr/games) alias h history alias ll ls -l 


Login shells rebuild the history list from the contents of ~/.history. If the histfile variable exists, tcsh uses the file that histfile points to in place of .history.


Login shells read and execute the commands in ~/.login. This file contains commands that you want to execute once, at the beginning of each session. You can use setenv (page 356) to declare environment (global) variables here. You can also declare the type of terminal you are using and set some terminal characteristics in your .login file.

 tcsh $ cat ~/.login setenv history 200 setenv mail /var/spool/mail/$user if ( -z $DISPLAY ) then         setenv TERM vt100     else         setenv TERM xterm endif stty erase '^h' kill '^u' -lcase tab3 date '+Login on %A %B %d at %I:%M %p' 

The preceding .login file establishes the type of terminal you are using by setting the TERM variable (the if statement [page 368] determines whether you are using a graphical interface and therefore what value should be assigned to TERM). It then runs stty (page 778) to set terminal characteristics and date (page 630) to display the time you logged in.

/etc/csh.logout and .logout

The TC Shell runs the /etc/csh.logout and ~/.logout files, in that order, when you exit from a login shell. The following sample .logout file uses date to display the time you logged out. The sleep command ensures that echo has time to display the message before the system logs you out. The delay may be useful for dial-up lines that take some time to display the message.

 tcsh $ cat ~/.logout date '+Logout on %A %B %d at %I:%M %p' sleep 5 

Features Common to the Bourne Again and TC Shells

Most of the features common to both bash and tcsh are derived from the original C Shell:

  • Command line expansion (also called substitution; page 344)

  • History (page 344)

  • Aliases (page 347)

  • Job control (page 348)

  • Filename substitution (page 348)

  • Directory stack manipulation (page 349)

  • Command substitution (page 349)

Because the chapters on bash discuss these features in detail, this section focuses on the differences between the bash and tcsh implementations.

Command Line Expansion (Substitution)

Refer to "Processing the Command Line" on page 322 for an introduction to command line expansion in the Bourne Again Shell. The tcsh man page uses the term substitution instead of expansion, which is used by bash. The TC Shell scans each token for possible expansion in the following order:

  1. History substitution (page 344)

  2. Alias substitution (page 347)

  3. Variable substitution (page 356)

  4. Command substitution (page 349)

  5. Filename substitution (page 348)

  6. Directory stack substitution (page 349)


The TC Shell assigns a sequential event number to each command line. You can display this event number as part of the tcsh prompt (refer to "prompt" on page 363). Examples in this section show numbered prompts when they help illustrate the behavior of a command.

history Builtin

As in bash, the tcsh history builtin displays the events in your history list. The list of events is ordered with the oldest events at the top. The last event in the history list is the history command that displayed the list. In the following history list, which is limited to ten lines by the argument of 10 to the history command, command 23 modifies the tcsh prompt to display the history event number. The time each command was executed appears to the right of the event number.

 32 $ history 10     23  23:59   set prompt = "! $ "     24  23:59   ls -l     25  23:59   cat temp     26  0:00    rm temp     27  0:00    vim memo     28  0:00    lpr memo     29  0:00    vim memo     30  0:00    lpr memo     31  0:00    rm memo     32  0:00    history 

History Expansion

The same event and word designators work in both shells. For example, !! refers to the previous event in tcsh, just as it does in bash. The command !328 executes event number 328 and !?txt? executes the most recent event containing the string txt. For more information refer to "Using an Exclamation Point (!) to Reference Events" on page 300. Table 9-1 lists the few tcsh word modifiers not found in bash.

Table 9-1. Word modifiers




Converts the first lowercase letter into uppercase


Converts the first uppercase letter into lowercase


Applies the next modifier globally within a single word

You can use more than one word modifier in a command. For instance, the a modifier, in combination with the u or l modifier, enables you to change the case of an entire word.

 tcsh $ echo $VERSION VERSION: Undefined variable. tcsh $ echo !!:1:al echo $version tcsh 6.12.00 (Astron) 2002-07-23 (i386-intel-linux) options 8b,nls,... 

In addition to using event designators to access the history list, you can use the command line editor to access, modify, and execute previous commands (page 353).


The variables that you set to control history in tcsh are different from those used in bash. Whereas bash uses HISTSIZE and HISTFILESIZE to determine the number of events that are preserved during and between sessions, tcsh uses history and savehist (Table 9-2) for these purposes.

Table 9-2. History variables





100 events

Maximum number of events saved during a session



Location of the history file


not set

Maximum number of events saved between sessions

history and savehist

When you exit from a tcsh shell, the most recently executed commands are saved in your ~/.history file. The next time you start the shell this file initializes the history list. The value of the savehist variable determines the number of lines saved in the .history file (not necessarily the same as the history variable). If savehist is not set, tcsh does not save history between sessions. The history and savehist variables must be local (declared with set, not setenv). The history variable holds the number of events remembered during a session and the savehist variable holds the number remembered between sessions. See Table 9-2.

If you set the value of history too high, it can use too much memory. If it is unset or set to zero, the shell does not save any commands. To establish a history list of the 500 most recent events, give the following command manually or place it in your ~/.tcshrc startup file:

 tcsh $ set history = 500 

The following command causes tcsh to save the 200 most recent events across login sessions:

 tcsh $ set savehist = 200 

You can combine these two assignments into a single command:

 tcsh $ set history=500 savehist=200 

After you set savehist you can log out and log in again, and the 200 most recent events from the previous login sessions will appear in your history list. Set savehist in your ~/.tcshrc file if you want to maintain your event list from login to login.


If you set the variable histlit (history literal), history displays the commands in the history list exactly as they were typed in without any shell interpretation. The following example shows the effect of this variable (compare the lines numbered 32):

 tcsh $ cat /etc/csh.cshrc ... tcsh $ cp !!:1 ~ cp /etc/csh.cshrc ~  tcsh $ set histlit tcsh $ history ...     31  9:35    cat /etc/csh.cshrc     32  9:35    cp !!:1 ~     33  9:35    set histlit     34  9:35    history tcsh $ unset histlit tcsh $ history ...     31  9:35    cat /etc/csh.cshrc     32  9:35    cp /etc/csh.cshrc ~     33  9:35    set histlit     34  9:35    history     35  9:35    unset histlit     36  9:36    history 


There is a difference in how bash and tcsh expand history event designators. If you give the command !250w, bash replaces it with command number 250 with a character w appended to it. In contrast, tcsh looks back through your history list for an event that begins with the string 250w to execute. The reason for the difference: bash interprets the first three characters of 250w as the number of a command, whereas tcsh interprets those characters as part of the search string 250w. (If the 250 stands alone, tcsh treats it as a command number.)

If you want to append w to command number 250, you can insulate the event number from the w by surrounding it with braces:



The alias/unalias feature in tcsh closely resembles its counterpart in bash (page 312). However, the alias builtin has a slightly different syntax:

 alias name value 

The following command creates an alias for ls:

 tcsh $ alias ls "ls -lF" 

The tcsh alias allows you to substitute command line arguments, whereas bash does not:

 $ alias nam "echo Hello, \!^ is my name" $ nam Sam Hello, Sam is my name 

The string \!* within an alias expands to all command line arguments:

 $ alias sortprint "sort \!* | lpr" 

The next alias displays its second argument:

 $ alias n2 "echo \!:2" 

Special Aliases

Some alias names, called special aliases, have special meaning to tcsh. If you define an alias with one of these names, tcsh executes it automatically as explained in Table 9-3. Initially all special aliases are undefined.

Table 9-3. Special aliases


When executed


Whenever the shell would normally ring the terminal bell. Gives you a way to have other visual or audio effects take place at those times.


Whenever you change to another working directory.


Periodically, as determined by the number of minutes in the tperiod variable. If tperiod is unset or has the value 0, periodic has no meaning.


Just before the shell displays a prompt.


Gives the absolute pathname of the shell that you want to use to run scripts that do not start with #! (page 265).

To see a list of current aliases, give the command alias. To view the alias for a particular name, give the command alias followed by the name.

History Substitution In Aliases

You can substitute command line arguments by using the history mechanism, where a single exclamation point represents the command line containing the alias. Modifiers are the same as those used by history (page 300). In the following example, the exclamation points are quoted so that the shell does not interpret them when building the aliases:

 21 $ alias last echo \!:$ 22 $ last this is just a test test 23 $ alias fn2 echo \!:2:t 24 $ fn2 /home/jenny/test /home/alex/temp /home/barbara/new temp 

Event 21 defines for last an alias that displays the last argument. Event 23 defines for fn2 an alias that displays the simple filename, or tail, of the second argument on the command line.

Job Control

Job control is similar in both bash (page 271) and tcsh. You can move commands between the foreground and background, suspend jobs temporarily, and get a list of the current jobs. The % character references a job when followed by a job number or a string prefix that uniquely identifies the job. You will see a minor difference when you run a multiple-process command line in the background from each shell. Whereas bash displays only the PID number of the last background process in each job, tcsh displays the numbers for all processes belonging to a job. The example from page 271 looks like this under tcsh:

 tcsh $ find . -print | sort | lpr & grep -l alex /tmp/* > alexfiles & [1] 18839  18840    18841 [2] 18876 

Filename Substitution

The TC Shell expands the characters *, ?, and [ ] in a pathname just as bash does (page 127). The * matches any string of zero or more characters, ? matches any single character, and [ ] defines a character class, which is used to match single characters appearing within a pair of brackets.

The TC Shell expands command line arguments that start with a tilde (~) into filenames in much the same way that bash does (page 351), with the ~ standing for the user's home directory or the home directory of the user whose name follows the tilde. The bash special expansions ~ + and ~ are not available in tcsh.

Brace expansion (page 324) is available in tcsh. Like tilde expansion, it is regarded as an aspect of filename substitution even though brace expansion can generate strings that are not the names of actual files.

In tcsh and its predecessor csh, the process of using patterns to match filenames is referred to as globbing and the pattern itself is called a globbing pattern. If tcsh is unable to identify one or more files that match a globbing pattern, it reports an error (unless the pattern contains a brace). Setting the shell variable noglob suppresses filename substitution, including both tilde and brace interpretation.

Manipulating the Directory Stack

Directory stack manipulation in tcsh does not differ much from that in bash (page 274). The dirs builtin displays the contents of the stack, and the pushd and popd builtins push directories onto and pop directories off of the stack.

Command Substitution

The $(...) format for command substitution is not available in tcsh. In its place you must use the original '...' format. Otherwise, the implementation in bash and tcsh is identical. Refer to page 329 for more information on command substitution.

Redirecting Standard Error

Both bash and tcsh use a greater than symbol (>) to redirect standard output, but tcsh does not use the bash notation 2> to redirect standard error. Under tcsh you use a greater than symbol followed by an ampersand (>&) to combine and redirect standard output and standard error. Although you can use this notation under bash, it is not common. The following examples, like the bash examples on page 261, reference file x, which does not exist, and file y, which contains a single line.

 tcsh $ cat x cat: x: No such file or directory tcsh $ cat y This is y. tcsh $ cat x y >& hold tcsh $ cat hold cat: x: No such file or directory This is y. 

With an argument of y in the preceding example, cat sends a string to standard output. An argument of x causes cat to send an error message to standard error.

Unlike bash, tcsh does not provide a simple way to redirect standard error separately from standard output. A work-around frequently provides a reasonable solution. The following example runs cat with arguments of x and y in a subshell (the parentheses ensure that the command within them runs in a subshell see page 270). Also within the subshell a > redirects standard output to the file outfile. Output sent to standard error is not touched by the subshell but rather is sent to the parent shell, where both it and standard output are sent to errfile. Because standard output has already been redirected, errfile contains only output sent to standard error.

 tcsh $ (cat x y > outfile) >& errfile tcsh $ cat outfile This is y. tcsh $ cat errfile cat: x: No such file or directory 

It can be useful to combine and redirect output when you want to run a slow command in the background and do not want its output cluttering up the terminal screen. For example, because the find utility (page 655) often takes some time to complete, it may be a good idea to run it in the background. The next command finds in the filesystem hierarchy all files that contain the string biblio in their name. The command runs in the background and sends its output to the findout file. Because the find utility sends to standard error a report of directories that you do not have permission to search, the findout file contains a record of any files that are found as well as a record of the directories that could not be searched.

 tcsh $ find / -name "*biblio*" -print >& findout & 

In this example, if you did not combine standard error with standard output and redirected only standard output, the error messages would appear on the screen and findout would list only files that were found.

While a command that has its output redirected to a file is running in the background, you can look at the output by using tail (page 783) with the f option. The f option causes tail to display new lines as they are written to the file:

 tcsh $ tail -f findout 

To terminate the tail command, press the interrupt key (usually CONTROL-C).

Working with the Command Line

This section covers word completion, editing the command line, and correcting spelling.

Word Completion

The TC Shell completes filenames, commands, and variable names on the command line when you prompt it to do so. The generic term used to refer to all these features under tcsh is word completion.

Filename Completion

The TC Shell can complete a filename after you specify a unique prefix. Filename completion is similar to filename generation, but the goal of filename completion is to select a single file. Together they make it practical to use long, descriptive filenames.

To use filename completion when you are entering a filename on the command line, type enough of the name to identify the file in the directory uniquely and press TAB ; tcsh fills in the name and adds a SPACE, leaving the cursor so you can enter additional arguments or press RETURN. In the following example, the user types the command cat trig1A and presses TAB; the system fills in the rest of the filename that begins with trig1A:

 tcsh $ cat trig1A   cat trig1A.302488  

If two or more filenames match the prefix that you have typed, tcsh cannot complete the filename without obtaining more information from you. The shell attempts to maximize the length of the prefix by adding characters, if possible, and then beeps to signify that additional input is needed to resolve the ambiguity:

 tcsh $ ls h* help.hist  help.trig01  help.txt tcsh $ cat h   cat help. You can fill in enough characters to resolve the ambiguity and then press the TAB key again. Alternatively, you can press CONTROL-D to cause tcsh to display a list of matching filenames:

 tcsh $ cat help.   

After displaying the filenames tcsh redraws the command line so you can disambiguate the filename (and press TAB again) or finish typing the filename manually.

Tilde Completion

The TC Shell parses a tilde (~) appearing as the first character of a word and attempts to expand it to a username when you enter a TAB:

 tcsh $ cd ~al     pwd /home/alex 

By appending a slash (/), tcsh indicates that the completed word is a directory. The slash also makes it easy to continue specifying the pathname.

Command and Variable Completion

You can use the same mechanism that you use to list and complete filenames with command and variable names. Unless you give a full pathname, the shell uses the variable path in an attempt to complete a command name. The choices listed are likely to be located in different directories.

 tcsh $ up  (beep)     uptime   If you set the autolist variable as in the following example, the shell lists choices automatically when you invoke completion by pressing TAB. You do not have to press CONTROL-D.

 tcsh $ set autolist tcsh $ up  (beep) up2date              updatedb             uptime up2date-config       update-mime-database up2date-nox          updmap tcsh $ up    uptime   If you set autolist to ambiguous, the shell lists the choices when you press TAB only if the word you enter is the longest prefix of a set of commands. Otherwise, pressing TAB causes the shell to add one or more characters to the word until it is the longest prefix; pressing TAB again then lists the choices:

 tcsh $ set autolist=ambiguous tcsh $ echo $h  (beep) histfile history home tcsh $ echo $h     echo $hist       echo $history   The shell must rely on the context of the word within the input line to determine whether it is a filename, a username, a command, or a variable name. The first word on an input line is assumed to be a command name; if a word begins with the special character $, it is viewed as a variable name; and so on. In the following example, the second which command does not work properly: The context of the word up makes it look like the beginning of a filename rather than the beginning of a command. The TC Shell supplies which with an argument of updates (a nonexecutable file) and which displays an error message:

 tcsh $ ls up* updates tcsh $ which updatedb ups uptime /usr/bin/updatedb /usr/local/bin/ups /usr/bin/uptime tcsh $ which up   which updates updates: Command not found. 

Editing the Command Line

The tcsh command line editing feature is similar to that available under bash. You can use either emacs mode commands (default) or vi(m) mode commands. Change to vi(m) mode commands by using bindkey v and to emacs mode commands by using bindkey e. The ARROW keys are bound to the obvious motion commands in both modes, so you can move back and forth (up and down) through your history list as well as left and right on the current command line.

Without an argument, the bindkey builtin displays the current mappings between editor commands and the key sequences you can enter at the keyboard:

 tcsh $ bindkey Standard key bindings "^@"           ->  set-mark-command "^A"           ->  beginning-of-line "^B"           ->  backward-char "^C"           ->  tty-sigintr "^D"           ->  delete-char-or-list-or-eof ... Multi-character bindings "^[[A"         -> up-history "^[[B"         -> down-history "^[[C"         -> forward-char "^[[D"         -> backward-char "^[[H"         -> beginning-of-line "^[[F"         -> end-of-line ... Arrow key bindings down           -> down-history up             -> up-history left           -> backward-char right          -> forward-char home           -> beginning-of-line end            -> end-of-line 

The ^ indicates a CONTROL character (^B = CONTROL-B). The ^[ indicates a META or ALT character; you press and hold the META or ALT key while you press the key for the next character. If this substitution does not work or if the keyboard you are using does not have a META or ALT key, press and release the ESCAPE key and then press the key for the next character. For ^[[F you would press META-[ or ALT-[ followed by the F key or else ESCAPE [ F). The down/up/left/right indicate ARROW keys, and home/end indicate the HOME and END keys on the numeric keypad.

The preceding example shows the output from bindkey with the user in emacs mode. Change to vi(m) mode (bindkey v) and give another bindkey command to display the vi(m) key bindings. You can pipe the output of bindkey through less to make it easier to read the list.

Correcting Spelling

You can have tcsh attempt to correct the spelling of command names, filenames, and variables (but only using emacs-style key bindings). Spelling correction can take place only at two times: before and after you press RETURN.

before you press return

For tcsh to correct a word or line before you press RETURN, you must indicate that you want it to do so. The two functions for this purpose are spell-line and spell-word:

 $ bindkey | grep spell "^[$"          -> spell-line "^[S"          -> spell-word "^[s"          -> spell-word 

The output from bindkey shows that spell-line is bound to META-$ (ALT-$ or ESCAPE $) and spell-word is bound to META-S and META-s (ALT-s or ESCAPE s and ALT-S or ESCAPE S). To correct the spelling of the word to the left of the cursor, enter META-s. Entering META-$ invokes the spell-line function, which attempts to correct all words on a command line:

 tcsh $ ls bigfile.gz tcsh $ gunzipp   gunzip   gunzip bigfile.gz tcsh $ gunzip bigfele.gz   gunzip bigfile.gz tcsh $ ecno $usfr   echo $user 

After You Press Return

The variable named correct controls what tcsh attempts to correct or complete after you press RETURN and before it passes the command line to the command being called. If you do not set correct, tcsh will not correct anything:

 tcsh $ unset correct tcsh $ ls morning morning tcsh $ ecno $usfr morbing usfr: Undefined variable. 

The shell reports the error in the variable name and not the command name because it expands variables before it executes the command (page 344). When you give a bad command name without any arguments, the shell reports on the bad command name.

Set correct to cmd to correct only commands; all to correct commands, variables, and filenames; or complete to complete commands:

 tcsh $ set correct = cmd tcsh $ ecno $usfr morbing CORRECT>echo $usfr morbing (y|n|e|a)? y usfr: Undefined variable. tcsh $ set correct = all tcsh $ echo $usfr morbing CORRECT>echo $user morning (y|n|e|a)? y alex morning 

With correct set to cmd, tcsh corrects the command name from ecno to echo. With correct set to all, tcsh corrects both the command name and the variable. It would also correct a filename if one was present on the command line.

Automatic spell checking displays a special prompt that lets you enter y to accept the modified command line, n to reject it, e to edit it, or a to abort the command. Refer to "prompt3" on page 364 for a discussion of the special prompt used in spelling correction.

In the next example, after setting the correct variable the user mistypes the name of the ls command; tcsh then prompts for a correct command name. Because the command that tcsh has offered as a replacement is not ls, the user chooses to edit the command line. The shell leaves the cursor following the command so the user can correct the mistake:

 tcsh $ set correct=cmd tcsh $ lx -l  (beep) CORRECT>lex -l (y|n|e|a)? e tcsh $ lx -l  

If you assign the value complete to the variable correct, tcsh attempts command name completion in the same manner as filename completion (page 350). In the following example, after setting correct to complete the user enters the command up. The shell responds with Ambiguous command because several commands start with these two letters but differ in the third letter. The shell then redisplays the command line. The user could press TAB at this point to get a list of commands that start with up but decides to enter t and press RETURN. The shell completes the command because these three letters uniquely identify the uptime utility:

 tcsh $ set correct = complete tcsh $ upRETURN Ambiguous command tcsh $ up   uptime 4:45pm  up 5 days,  9:54,  5 users,  load average: 1.62, 0.83, 0.33 


Although tcsh stores variable values as strings, you can work with these variables as numbers. Expressions in tcsh can use arithmetic, logical, and conditional operators. The @ builtin can evaluate integer arithmetic expressions.

This section uses the term numeric variable to describe a string variable that contains a number that tcsh uses in arithmetic or logical arithmetic computations. However, no true numeric variables exist in tcsh.

Variable name

A tcsh variable name consists of 1 to 20 characters, which can be letters, digits, and underscores ( _). The first character cannot be a digit but can be an underscore.

Variable Substitution

Three builtins declare, display, and assign values to variables: set, @, and setenv. The set and setenv builtins both assume nonnumeric string variables. The @ builtin works only with numeric variables. Both set and @ declare local variables. The setenv builtin declares a variable and places it in the calling environment of all child processes (makes it global). Using setenv is similar to assigning a value to a variable and then using export in the Bourne Again Shell. See "Locality of Variables" on page 475 for a discussion of local and environment variables.

Once the value or merely the existence of a variable has been established, tcsh substitutes the value of that variable when the name of the variable, preceded by a dollar sign ($), appears on a command line. If you quote the dollar sign by preceding it with a backslash or enclosing it within single quotation marks, the shell does not perform the substitution. When a variable is within double quotation marks, the substitution occurs even if you quote the dollar sign by preceding it with a backslash.

String Variables

The TC Shell treats string variables similarly to the way the Bourne Again Shell does. The major difference is in their declaration and assignment: tcsh uses an explicit command, set (or setenv), to declare and/or assign a value to a string variable.

 tcsh $ set name = fred tcsh $ echo $name fred tcsh $ set argv    () cwd     /home/alex home    /home/alex name    fred path    (/usr/local/bin /bin /usr/bin /usr/X11R6/bin) prompt  $  shell   /bin/tcsh status  0 term    vt100 user    alex 

The first line in the example declares the variable name and assigns the string fred to it. Unlike bash, tcsh allows but does not demand SPACEs around the equal sign. The next line displays this value. When you give a set command without any arguments, it displays a list of all local shell variables and their values (your list will be longer than the one in the example). When you give a set command with the name of a variable and no value, the command sets the value of the variable to a null string.

You can use the unset builtin to remove a variable:

 tcsh $ set name tcsh $ echo $name tcsh $ unset name tcsh $ echo $name name: Undefined variable. 

With setenv you must separate the variable name from the string being assigned to it by one or more SPACEs and no equal sign. The tcsh command creates a subshell, echo shows that the variable and its value are known to the subshell, and exit returns to the original shell. Try this example, using set in place of setenv:

 tcsh $ setenv SCRDIR /usr/local/src tcsh $ tcsh tcsh $ echo $SCRDIR /usr/local/src tcsh $ exit 

If you use setenv with no arguments, it displays a list of the environment (global) variables variables that are passed to the shell's child processes. By convention, environment variables are named using uppercase letters.

As with set, giving setenv a variable name without a value sets the value of the variable to a null string. Although you can use unset to remove environment and local variables, unsetenv can remove only environment variables.

Arrays of String Variables

An array is a collection of strings, each of which is identified by its index (1, 2, 3, and so on). Arrays in tcsh use one-based indexing (the first element of the array has the subscript 1). Before you can access individual elements of an array, you must declare the entire array by assigning a value to each element of the array. The list of values must be enclosed in parentheses and separated by SPACEs:

 8 $ set colors = (red green blue orange yellow) 9 $ echo $colors red green blue orange yellow 10 $ echo $colors[3] blue 11 $ echo $colors[2-4] green blue orange 12 $ set shapes = ('' '' '' '' '') 13 $ echo $shapes 14 $ set shapes[4] = square 15 $ echo $shapes[4] square 

Event 8 declares the array of string variables named colors to have five elements and assigns values to each of them. If you do not know the values of the elements at the time you declare an array, you can declare an array containing the necessary number of null elements (event 12).

You can reference an entire array by preceding its name with a dollar sign (event 9). A number in brackets following a reference to the array refers to an element of the array (events 10, 14, and 15). Two numbers in brackets, separated by a hyphen, refer to two or more adjacent elements of the array (event 11). Refer to "Special Variable Forms" on page 361 for more information on arrays.

Numeric Variables

The @ builtin assigns the result of a numeric calculation to a numeric variable (as described under "Variables" [page 355], tcsh has no true numeric variables). You can declare single numeric variables with @, just as you can use set to declare nonnumeric variables. However, if you give it a nonnumeric argument, @ displays an error message. Just as set does, the @ command used without any arguments lists all shell variables.

Many of the expressions that the @ builtin can evaluate and the operators it recognizes are derived from the C programming language. The following format shows a declaration or assignment using @ (the SPACE after the @ is required):

 @ variable-name operator expression 

The variable-name is the name of the variable that you are assigning a value to. The operator is one of the C assignment operators: =, +=, =, *=, /=, or %=. (See page 533 for an explanation of these operators.) The expression is an arithmetic expression that can include most C operators (see the next section). You can use parentheses within the expression for clarity or to change the order of evaluation. Parentheses must surround parts of the expression that contain any of the following characters: <, >, &, or |.


An expression is composed of constants, variables, and most any of the bash operators (page 505). Expressions that involve files rather than numeric variables or strings are described in Table 9-8 on page 368.

Table 9-8. Value of n




File is a block special file


File is a character special file


File is a directory file


File exists


File is an ordinary or directory file


File has the set-group-ID bit set


File has the sticky bit (page 903) set


File is a symbolic link


File is owned by user


File is a named pipe (FIFO)


The user has read access to the file


File is not empty (has nonzero size)


File is a socket special file


File descriptor (a single digit replacing filename) is open and connected to the screen


File has the set-user-ID bit set


User has write access to the file


User has execute access to the file


File is either a builtin or an executable found by searching the directories in $path


File is 0 bytes long

Expressions follow these rules:

  1. The shell evaluates a missing or null argument as 0.

  2. All results are decimal numbers.

  3. Except for != and = =, the operators act on numeric arguments.

  4. You must separate each element of an expression from adjacent elements by a SPACE, unless the adjacent element is &, |, <, >, ( , or ).

tip: Do not use $ when assigning a value to a variable

As with bash, variables having a value assigned to them (those on the left of the operator) must not be preceded by a dollar sign ($). Thus

     tcsh $ @ $answer = 5 + 5 will yield      answer: Undefined variable. 

or, if answer is defined,

      @: Variable name must begin with a letter. 


      tcsh $ @ answer = 5 + 5 

assigns the value 10 to the variable answer.

Following are some examples that use @:

 216 $ @ count = 0 217 $ echo $count 0 218 $ @ count = ( 10 + 4 ) / 2 219 $ echo $count 7 220 $ @ result = ( $count < 5 ) 221 $ echo $result 0 222 $ @ count += 5 223 $ echo $count 12 224 $ @ count++ 225 $ echo $count 13 

Event 216 declares the variable count and assigns it a value of 0. Event 218 shows the result of an arithmetic operation being assigned to a variable. Event 220 uses @ to assign the result of a logical operation involving a constant and a variable to result. The value of the operation is false (= 0) because the variable count is not less than 5. Event 222 is a compressed form of the following assignment statement:

 tcsh $ @ count = $count + 5 

Event 224 uses a postfix operator to increment count by 1.

Postincrement and postdecrement operators

You can use the postincrement (++) and postdecrement ( ) operators only in expressions containing a single variable name, as shown in the following example:

 tcsh $ @ count = 0 tcsh $ @ count++ tcsh $ echo $count 1 tcsh $ @ next = $count++ @: Badly formed number. 

Unlike in the C programming language and bash, expressions in tcsh cannot use preincrement and predecrement operators.

Arrays of Numeric Variables

You must use the set builtin to declare an array of numeric variables before you can use @ to assign values to the elements of that array. The set builtin can assign any values to the elements of a numeric array, including zeros, other numbers, and null strings.

Assigning a value to an element of a numeric array is similar to assigning a value to a simple numeric variable. The only difference is that you must specify the element, or index, of the array. The syntax is

 @ variable-name[index] operator expression 

The index specifies the element of the array that is being addressed. The first element has an index of 1. The index cannot be an expression but must be either a numeric constant or a variable. In the preceding syntax the brackets around index are part of the syntax and do not indicate that index is optional. If you specify an index that is too large for the array you declared with set, tcsh displays @: Subscript out of range.

 226 $ set ages = (0 0 0 0 0) 227 $ @ ages[2] = 15 228 $ @ ages[3] = ($ages[2] + 4) 229 $ echo $ages[3] 19 230 $ echo $ages 0 15 19 0 0 231 $ set index = 3 232 $ echo $ages[$index] 19 233 $ echo $ages[6] ages: Subscript out of range. 

Elements of a numeric array behave as though they were simple numeric variables. Event 226 declares an array with five elements, each having a value of 0. Events 227 and 228 assign values to elements of the array, and event 229 displays the value of one of the elements. Event 230 displays all the elements of the array, 232 specifies an element by using a variable, and 233 demonstrates the out-of-range error message.


Like with bash, tcsh allows you to use braces to distinguish a variable from surrounding text without the use of a separator:

 $ set bb=abc $ echo $bbdef bbdef: Undefined variable. $ echo ${bb}def abcdef 

Special Variable Forms

The special variable with the following syntax has the value of the number of elements in the variable-name array:


You can determine whether variable-name has been set by looking at the value of the variable with the following syntax:


This variable has a value of 1 if variable-name is set and 0 otherwise:

 tcsh $ set days = (mon tues wed thurs fri) tcsh $ echo $#days 5 tcsh $ echo $?days 1 tcsh $ unset days tcsh $ echo $?days 0 

Reading User Input

Within a tcsh shell script, you can use the set builtin to read a line from the terminal and assign it to a variable. The following portion of a shell script prompts the user and reads a line of input into the variable input_line:

 echo -n "Enter input: " set input_line = "$<" 

The value of the shell variable $< is a line from standard input. The quotation marks around $< keep the shell from assigning only the first word of the line of input to the variable input_line.

Shell Variables

TC Shell variables may be set by the shell, inherited by the shell from the environment, or set by the user and used by the shell. Some variables take on significant values (for example, the PID number of a background process). Other variables act as switches: on if they are declared and off if they are not. Many of the shell variables are often set from one of tcsh's two startup files: ~/.login and ~/.tcshrc (page 342).

Shell Variables That Take On Values


Contains the command line arguments (positional parameters) from the command line that invoked the shell. Like all tcsh arrays, this array uses one-based indexing; argv[1] contains the first command line argument. You can abbreviate references to $argv[n] as $n. The token argv[*] references all the arguments together; you can abbreviate it as $*. Use $0 to reference the name of the calling program. Refer to "Positional Parameters" on page 480. The Bourne Again Shell does not use the argv form, only the abbreviated form.

$#argv or $#

Holds the number of elements in the argv array. Refer to "Special Variable Forms" on page 361.


Controls command and variable completion (page 351).


Enables tcsh's automatic logout facility, which logs you out if you leave the shell idle for too long. The value of the variable is the number of minutes of inactivity that tcsh waits before logging you out. The default is 60 minutes if you are Superuser. This variable is initially unset for other users.


Affects the operation of cd in the same way as the CDPATH variable does in bash (page 289). The cdpath variable is assigned an array of absolute pathnames (see path, later in this section) and is usually set in the ~/.login file with a command line such as the following:

 tcsh $ set cdpath = (/home/scott /home/scott/letters) 


When you call cd with a simple filename, it searches the working directory for a subdirectory with that name. If one is not found, cd searches the directories listed in cdpath for the subdirectory.


Set to cmd for automatic spelling correction of command names, to all to correct the entire command line, and to complete for automatic completion of command names. This variable works on corrections that are made after you press RETURN. Refer to "After You Press RETURN" on page 354.


The shell sets this variable to the name of the working directory. When you access a directory through a symbolic link (page 99), tcsh sets cwd to the name of the symbolic link.


The shell keeps the stack of directories used with the pushd, popd, and dirs builtins in this variable. For more information refer to "Manipulating the Directory Stack" on page 274.


Holds an array of suffixes that tcsh ignores during filename completion.


The shell sets this variable to your group ID.


Holds the full pathname of the file that saves the history list between login sessions (page 345). The defaults is ~/.history.


Specifies the size of your history list. Refer to "History" on page 344.

home or HOME

Holds the pathname of the user's home directory. The cd builtin refers to this variable, as does the filename substitution of ~ (page 326).


Specifies files and directories to check for mail. The TC Shell checks for new mail every 10 minutes unless the first word of mail is a number, in which case that number specifies how often the shell should check in seconds.


The shell keeps the name of your previous (old) working directory in this variable, which is equivalent to ~ in bash.

path or PATH

Holds a list of directories that tcsh searches for executable commands (page 284). If this array is empty or unset, you can execute commands only by giving their full pathnames. You can set path with a command such as the following:

 tcsh $ set path = ( /usr/bin /bin /usr/local/bin  /usr/bin/X11 ~/bin . ) 


Holds the primary prompt, similar to the bash PS1 variable (page 286). If it is not set, the prompt is >, or # for root (Superuser). The shell expands an exclamation point in the prompt string to the current event number. The following is a typical line from a .tcshrc file that sets the value of prompt:

 set prompt = '! $ ' 

Table 9-4 lists a number of special formatting sequences you can use in prompt to achieve special effects.

Table 9-4. prompt formatting sequences


Displays in prompt


Value of cwd (the working directory)


Same as %/, but replaces the path of the user's home directory with a tilde

%! or %h or !

Current event number


Hostname without the domain


Full hostname, including the domain


User's username


Time of day through the current minute


Time of day through the current second


Day of the week


Day of the month


Month as mm


Year as yy


Year as yyyy


A pound sign (#) if the user is running as root (Superuser); otherwise a greater than sign (>)


Exit status of the preceding command


Holds the prompt used in foreach and while control structures (pages 373 and 375). The default value is '%R? ', where R is replaced by the word while if you are inside a while structure and foreach if you are inside a foreach structure.


Holds the prompt used during automatic spelling correction. The default value is 'CORRECT>%R (y|n|e|a)?', where R is replaced by the corrected string.


Specifies the number of commands saved from the history list when you log out. These events are saved in a file named ~/.history. The shell uses these events as the initial history list when you log in again, causing your history list to continue across login sessions (page 345).


Holds the pathname of the shell you are using.


Is incremented each time you start a subshell and decremented each time you exit a subshell. The value is set to 1 for login a shell.


Contains the exit status returned by the last command. Similar to $? in bash (page 479).


Holds the version number of tcsh that you are running.


Provides two functions: automatic timing of commands using the time builtin and the format used by time. You can set this variable to either a single numeric value or an array holding a numeric value and a string. The numeric value is used to control automatic timing; any command that takes more than that number of CPU seconds to run has time display the command statistics when it finishes execution. A value of 0 results in statistics being displayed after every command. The string controls the formatting of the statistics using special formatting sequences, including those listed in Table 9-5.

Table 9-5. time formatting sequences




Time the command spent running user code, in CPU seconds (user mode)


Time the command spent running system code, in CPU seconds (kernel mode)


Wall clock time (total elapsed) taken by the command


Percentage of time the CPU spent on this task during this period, computed as (%U+%S)/%E


Number of times the command's processes were swapped out to disk


Average amount of shared code memory used by the command, in kilobytes


Average amount of data memory used by the command, in kilobytes


Total memory used by the command (as %X+%D), in kilobytes


Maximum amount of memory used by the command, in kilobytes


Number of major page faults (pages of memory that had to be read from disk)


Number of input operations


Number of output operations

By default the time builtin uses the string

 "%Uu %Ss %E %P%  %X+%Dk %I+%Oio %Fpf+%Ww" 

which generates output in the following format:

 tcsh $ time 0.200u 0.340s 17:32:33.27 0.0%      0+0k 0+0io 1165pf+0w 

You can time commands when you are concerned about system performance. If your commands consistently show many page faults and swaps, your system is probably memory starved and you should consider adding more memory to the system. You can use the information that time reports to compare the performance of various system configurations and program algorithms.


Controls how often, in minutes, the shell executes the special periodic alias (page 347).


The shell sets this variable to your username.


The shell sets this variable to contain detailed information about the version of tcsh you are using.


Set to an array of user and terminal pairs to watch for logins and logouts. The word any means any user or any terminal, so (any any) monitors all logins and logouts on all terminals, and (scott ttyS1 any console $user any) watches for scott on ttyS1, any user who accesses the system console, and any logins and logouts that use your account (presumably to catch intruders). By default logins and logouts are checked once every 10 minutes, but you can change this value by beginning the array with a numeric value giving the number of minutes between checks. If you set watch to (1 any console), logins and logouts by any user on the console will be checked once a minute. Reports are displayed just before a new shell prompt is issued. Also, the log builtin forces an immediate check whenever it is executed. See who for information about how you can control the format of the watch messages.


Controls the format of the information displayed in watch messages (Table 9-6).

Table 9-6. who formatting sequence






Action taken by user


Terminal on which action took place


Full hostname of remote host (or local if none) from which action took place


Hostname without domain name

The default string used for watch messages when who is unset is "%n has %a %l from %m", which generates the following line:

 jenny has logged on tty2 from local 


As in bash, this variable contains the PID number of the current shell; use it as $$.

Shell Variables That Act as Switches

The following shell variables act as switches; their values are not significant. If the variable has been declared, the shell takes the specified action. If not, the action is not taken or is negated. You can set these variables in your ~/.tcshrc startup file, in a shell script, or from the command line.


Causes the shell to attempt spelling correction automatically, just before each attempt at completion.


Normally pushd blindly pushes the new working directory onto the directory stack, meaning that you can end up with many duplicate entries on this stack. Set dunique to cause the shell to look for and delete any entries that duplicate the one it is about to push.


Causes the shell to display each command before it executes that command. Set echo by calling tcsh with the x option or by using set.


Enables filename completion (page 350) when running tcsh as csh (and csh is linked to tcsh).


Displays the commands in the history list exactly as entered, without interpretation by the shell (page 346).


Prevents you from using CONTROL-D to exit from a shell so you cannot accidentally log out. When this variable is declared, you must use exit or logout to leave a shell.


Causes the shell to list all jobs whenever a job is suspended.


Causes the ls F builtin to show the type of file each symbolic link points to instead of marking the symbolic link with an @ symbol.


Set by the shell if the current shell is running as a login shell.


Disables all beeping by the shell.


Prevents you from accidentally overwriting a file when you redirect output and prevents you from creating a file when you attempt to append output to a nonexistent file (Table 9-7). To override noclobber, add an exclamation point to the symbol you use for redirecting or appending output (for example, >! and >>!). For more information see page 119.

Table 9-7. How noclobber works

Command line

noclobber not declared

noclobber declared

x > fileout

Redirects standard output from process x to fileout. Overwrites fileout if it exists.

Redirects standard output from process x to fileout. The shell displays an error message if fileout exists and does not overwrite the file.

x >> fileout

Redirects standard output from process x to fileout. Appends new output to the end of fileout if it exists. Creates fileout if it does not exist.

Redirects standard output from process x to fileout. Appends new output to the end of fileout if it exists. The shell displays an error message if fileout does not exist and does not create the file.


Prevents the shell from expanding ambiguous filenames. Allows you to use *, ?, ~, and [ ] on the command line or in a shell script without quoting them.


Causes the shell to pass an ambiguous file reference that does not match a filename to the command that is being called. The shell does not expand the file reference. When you do not set nonomatch, tcsh generates a No match error message and does not execute the command.

 tcsh $ cat questions? cat: No match tcsh $ set nonomatch tcsh $ cat questions? cat: questions?: No such file or directory 


When set, tcsh sends a message to the screen immediately whenever a background job completes. Ordinarily tcsh notifies you about job completion just before displaying the next prompt. Refer to "Job Control" on page 271.


Causes a call to pushd without any arguments to change directories to your home directory (equivalent to pushd ).


Causes pushd and popd not to display the directory stack.


Causes the shell to request confirmation when you give an rm * command.


Causes the shell to display each command after a history expansion (page 344). Set verbose by calling tcsh with the v option or by using set.


Causes audible beeps to be replaced by flashing the screen.

Control Structures

The TC Shell uses many of the same control structures as the Bourne Again Shell. In each case the syntax is different, but the effects are the same. This section summarizes the differences between the control structures in the two shells. For more information refer to "Control Structures" on page 436.


The syntax of the if control structure is

 if (expression) simple-command 

The if control structure works only with simple commands, not with pipes or lists of commands. You can use the if...then control structure (page 372) to execute more complex commands.

 tcsh $ cat if_1 #!/bin/tcsh # Routine to show the use of a simple if control structure. # if ( $#argv == 0 ) echo "if_1: there are no arguments" 

The if_1 script checks whether it was called without any arguments. If the expression enclosed in parentheses evaluates to true that is, if zero arguments were on the command line the if structure displays a message.

In addition to logical expressions such as the one the if_1 script uses, you can use expressions that return a value based on the status of a file. The syntax for this type of expression is

  n filename 

where n is from the list in Table 9-8.

If the result of the test is true, the expression has a value of 1; if it is false, the expression has a value of 0. If the specified file does not exist or is not accessible, tcsh evaluates the expression as 0. The following example checks whether the file specified on the command line is an ordinary or directory file (and not a device or other special file):

 tcsh $ cat if_2 #!/bin/tcsh if -f $1 echo "Ordinary or Directory file" 

You can combine operators where it makes sense. For example, ox filename is true if you own and have execute permission for the file. This expression is equivalent to o filename && x filename.

Some operators return useful information about a file other than reporting true or false. They use the same n filename format, where n is one of the values shown in Table 9-9.

Table 9-9. Value of n




The last time the file was accessed.[*]


The last time the file was accessed displayed in a human-readable format.


The last time the file was modified.[*]


The last time the file was modified displayed in a human-readable format.


The last time the file's inode was modified.[*]


The last time the file's inode was modified displayed in a human-readable format.


Device number for the file. This number uniquely identifies the device (disk partition, for example) on which the file resides.


Inode number for the file. The inode number uniquely identifies a file on a particular device.


A string of the form device:inode. This string uniquely identifies a file anywhere on the system.


Number of hard links to the file.


The file's permissions, shown in octal, without a leading 0.


Numeric user ID of the file's owner.


Username of the file's owner.


Numeric group ID of the file's group.


Name of the file's group.


Number of bytes in the file.

[*] Time measured in seconds from the epoch (usually the start of January 1, 1970).

You can use only one of these operators in a given test, and it must appear as the last operator in a multiple-operator sequence. Because 0 can be a valid response from some of these operators (for instance, the number of bytes in a file might be 0), most return 1 on failure instead of the 0 that the logical operators return on failure. The one exception is F, which returns a colon if it cannot determine the device and inode for the file.

When you want to use one of these operators outside of a control structure expression, you can use the filetest builtin to evaluate a file test and report the result:

 tcsh $ filetest -z if_1 0 tcsh $ filetest -F if_1 2051:12694 tcsh $ filetest -Z if_1 131 


The goto statement has the following syntax:

 goto label 

A goto builtin transfers control to the statement beginning with label:. The following script fragment demonstrates the use of goto:

 tcsh $ cat goto_1 #!/bin/tcsh # # test for 2 arguments # if ($#argv == 2) goto goodargs echo "Usage: goto_1 arg1 arg2" exit 1 goodargs: ... 

The goto_1 script displays a usage message (page 440) when it is called with more or fewer than two arguments.

Interrupt Handling

The onintr statement transfers control when you interrupt a shell script. The format of an onintr statement is

 onintr label 

When you press the interrupt key during execution of a shell script, the shell transfers control to the statement beginning with label:. This statement allows you to terminate a script gracefully when it is interrupted. You can use it to ensure that when you interrupt a shell script, the script removes temporary files before returning control to the parent shell.

The following script demonstrates onintr. It loops continuously until you press the interrupt key, at which time it displays a message and returns control to the shell:

 tcsh $ cat onintr_1 #!/bin/tcsh # demonstration of onintr onintr close while ( 1 )     echo "Program is running."     sleep 2 end close: echo "End of program." 

If a script creates temporary files, you can use onintr to remove them.

 close: rm -f /tmp/$$* 

The ambiguous file reference /tmp/$$* matches all files in /tmp that begin with the PID number of the current shell. Refer to page 478 for a description of this technique for naming temporary files.


The if...then...else control structure has three forms. The first form, an extension of the simple if structure, executes more complex commands or a series of commands if expression is true. This form is still a one-way branch.

 if (expression) then     commands endif 

The second form is a two-way branch. If expression is true, the first set of commands is executed. If it is false, the set of commands following else is executed.

 if (expression) then     commands else     commands endif 

The third form is similar to the if...then...elif structure (page 442). It performs tests until it finds an expression that is true and then executes the corresponding commands.

 if (expression) then      commands else if (expression) then     commands . . . else      commands endif 

The following program assigns a value of 0, 1, 2, or 3 to the variable class based on the value of the first command line argument. The program declares the variable class at the beginning for clarity; you do not need to declare it before its first use. Also for clarity, the script assigns the value of the first command line argument to number.

 tcsh $ cat if_else_1 #!/bin/tcsh # routine to categorize the first # command line argument set class set number = $argv[1] # if ($number < 0) then     @ class = 0 else if (0 <= $number && $number < 100) then     @ class = 1 else if (100 <= $number && $number < 200) then     @ class = 2 else     @ class = 3 endif # echo "The number $number is in class ${class}." 

The first if statement tests whether number is less than 0. If it is, the script assigns 0 to class and transfers control to the statement following endif. If it is not, the second if tests whether the number is between 0 and 100. The && is the Boolean AND operator, yielding a value of true if the expression on each side is true. If the number is between 0 and 100, 1 is assigned to class and control is transferred to the statement following endif. A similar test determines whether the number is between 100 and 200. If it is not, the final else assigns 3 to class. The endif closes the if control structure. The final statement uses braces ({ } ) to isolate the variable class from the following period. The braces isolate the period for clarity; the shell does not consider a punctuation mark to be part of a variable name. The braces would be required if you wanted other characters to follow immediately after the variable.


The foreach structure parallels the bash structure (page 449). The syntax is

 foreach loop-index (argument-list)      commands end 

This structure loops through commands. The first time through the loop, the structure assigns the value of the first argument in argument-list to loop-index. When control reaches the end statement, the shell assigns the value of the next argument from argument-list to loop-index and executes the commands again. The shell repeats this procedure until it exhausts argument-list.

The following tcsh script uses a foreach structure to loop through the files in the working directory containing a specified string of characters in their filename and to change the string. For example, you can use it to change the string memo in filenames to letter. The filenames memo.1, dailymemo, and memories would change to letter.1, dailyletter, and letterries.

This script requires two arguments: the string to be changed (the old string) and the new string. The argument-list of the foreach structure uses an ambiguous file reference to loop through all filenames that contain the first argument. For each filename that matches the ambiguous file reference, the mv utility changes the filename. The echo and sed commands appear within back ticks (') that indicate command substitution: Executing the commands within the back ticks replaces the back ticks and everything between them. Refer to "Command Substitution" on page 329 for more information. The sed utility (page 563) substitutes the first argument for the second argument in the filename. The $1 and $2 are abbreviated forms of $argv[1] and $argv[2].

 tcsh $ cat ren #!/bin/tcsh # Usage:        ren arg1 arg2 #               changes the string arg1 in the names of files #               in the working directory into the string arg2 if ($#argv != 2) goto usage foreach i ( *$1* )     mv $i 'echo $i | sed -n s/$1/$2/p' end exit 0 usage: echo "Usage: ren arg1 arg2" exit 1 


The next script uses a foreach loop to assign the command line arguments to the elements of an array named buffer:

 tcsh $ cat foreach_1 #!/bin/tcsh # routine to zero-fill argv to 20 arguments # set buffer = (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) set count = 1 # if ($#argv > 20) goto toomany # foreach argument ($argv[*])     set buffer[$count] = $argument     @ count++ end # REPLACE command ON THE NEXT LINE WITH # THE PROGRAM YOU WANT TO CALL. exec command $buffer[*] # toomany: echo "Too many arguments given." echo "Usage: foreach_1 [up to 20 arguments]" exit 1 

The foreach_1 script calls another program named command with a command line guaranteed to contain 20 arguments. If foreach_1 is called with fewer than 20 arguments, it fills the command line with zeros to complete the 20 arguments for command. Providing more than 20 arguments causes it to display a usage message and exit with an error status of 1.

The foreach structure loops through the commands one time for each command line argument. Each time through the loop, foreach assigns the value of the next argument from the command line to the variable argument. Then the script assigns each of these values to an element of the array buffer. The variable count maintains the index for the buffer array. A postfix operator increments the count variable using @ (@ count++). The exec builtin (bash and tcsh; page 491) calls command so that a new process is not initiated. (Once command is called, the process running this routine is no longer needed so a new process is not required.)


The syntax of the while structure is

 while (expression)     commands end 

This structure continues to loop through commands while expression is true. If expression is false the first time it is evaluated, the structure never executes commands.

 tcsh $ cat while_1 #!/bin/tcsh # Demonstration of a while control structure. # This routine sums the numbers between 1 and n, # with n being the first argument on the command # line. # set limit = $argv[1] set index = 1 set sum = 0 # while ($index <= $limit)     @ sum += $index     @ index++ end # echo "The sum is $sum" 

This program computes the sum of all integers up to and including n, where n is the first argument on the command line. The += operator assigns the value of sum + index to sum.

break and continue

You can interrupt a foreach or while structure with a break or continue statement. These statements execute the remaining commands on the line before they transfer control. The break statement transfers control to the statement after the end statement, terminating execution of the loop. The continue statement transfers control to the end statement, which continues execution of the loop.


The switch structure is analogous to the bash case structure (page 459):

 switch (test-string)     case pattern:         commands     breaksw     case pattern:         commands     breaksw     ...     default:         commands     breaksw endsw 

The breaksw statement transfers control to the statement following the endsw statement. If you omit a breaksw, control falls through to the next command. You can use any of the special characters listed in Table 11-2 on page 462 within pattern except the pipe symbol ( | ).

 tcsh $ cat switch_1 #!/bin/tcsh # Demonstration of a switch control structure. # This routine tests the first command line argument # for yes or no in any combination of uppercase and # lowercase letters. # # # test that argv[1] exists if ($#argv != 1) then     echo "Usage: switch_1 [yes|no]"     exit 1 else # argv[1] exists, set up switch based on its value     switch ($argv[1])     # case of YES         case [yY][eE][sS]:         echo "Argument one is yes."         breaksw     #     # case of NO         case [nN][oO]:         echo "Argument one is no."     breaksw     #     # default case         default:         echo "Argument one is neither yes nor no."         breaksw     endsw endif 


Builtins are commands that are part of (built into) the shell. When you give a simple filename as a command, the shell first checks whether it is the name of a builtin. If it is, the shell executes it as part of the calling process; the shell does not fork a new process to execute the builtin. The shell does not need to search the directory structure for builtin programs because they are immediately available to the shell.

If the simple filename you give as a command is not a builtin, the shell searches the directory structure for the program you want, using the PATH variable as a guide. When it finds the program the shell forks a new process to execute the program.

Although they are not listed in Table 9-10, the control structure keywords (if, foreach, endsw, and so on) are builtins. The table describes many of the tcsh builtins, some of which are also built into other shells.

Table 9-10. tcsh builtins



% job

A synonym for the fg builtin. The job is the job number of the job you want to bring to the foreground (page 272).

% job &

A synonym for the bg builtin. The job is the number of the job you want to put in the background (page 273).


Similar to the set builtin but evaluates numeric expressions. Refer to "Numeric Variables" on page 358.


Creates and displays aliases; bash uses a different syntax than tcsh. Refer to "Aliases" on page 347.


Displays a report of the amount of free and used memory.


Moves a suspended job into the background (page 273).


Controls the mapping of keys to the tcsh command line editor commands.


Without any arguments, bindkey lists all key bindings (page 353).

bindkey l

Lists all available editor commands along with a short description of each.

bindkey e

Puts the command line editor in emacs mode (page 353).

bindkey v

Puts the command line editor in vi(m) mode (page 353).

bindkey key command

Attaches the editor command command to the key key.

bindkey b key command

Similar to the previous form but allows you to specify control keys by using the form C x (where x is the character you type while you press the CONTROL key), specify meta key sequences as M x (on most keyboards used with Linux, the ALT key is the meta key), and specify function keys as F-x.

bindkey c key command

Binds the key key to the command command. Here the command is not an editor command but either a shell builtin or an executable program.

bindkey s key string

Whenever you type key, string is substituted.


Displays a list of all builtins.

cd or chdir

Changes working directories (page 82).


Displays the directory stack (page 274).


Displays its arguments. You can prevent echo from displaying a RETURN at the end of a line by using the n option (see "Reading User Input" on page 361) or by using a trailing \c (see "read: Accepts User Input: Accepts User Input" on page 487). The echo builtin is similar to the echo utility (page 647).


Scans and evaluates the command line. When you put eval in front of a command, the command is scanned twice by the shell before it is executed. This feature is useful with a command that is generated by command or variable substitution. Because of the order in which the shell processes a command line, it is sometimes necessary to repeat the scan to achieve the desired result (page 318).


Overlays the program currently being executed with another program in the same shell. The original program is lost. Refer to "exec: Executes a Command: Executes a Command" on page 491 for more information; also refer to source (page 380).


Exits from a TC Shell. When you follow it with a numeric argument, tcsh returns that number as the exit status (page 479).


Moves a job into the foreground (page 271).


Takes one of the file inquiry operators followed by one or more filenames and applies the operator to each filename (page 370). Returns the results as a space-separated list.


Like echo, but does not display SPACEs between its arguments and does not follow its display with a NEWLINE.


Reports on the efficiency of tcsh's hash mechanism. The hash mechanism speeds the process of searching through the directories in your search path. See also rehash (page 380) and unhash (page 381).


Displays a list of recent commands (page 344).


Displays a list of jobs (suspended commands and those running in the background).


Terminates a job or process (page 497).


Limits the computer resources that the current process and any processes it creates can use. You can put limits on the number of seconds of CPU time the process can use, the size of files that the process can create, and so forth.


Immediately produces the report that the watch shell variable (page 365) would normally produce every 10 minutes.


Logs in a user. Can be followed by a username.


Ends a session if you are using your original (login) shell.

ls F

Similar to ls F but faster. (This builtin is the characters ls F without any SPACEs.)


Lowers the processing priority of a command or a shell. It is useful if you want to run a command that makes large demands on the system and you do not need the output right away. If you are Superuser, you can use nice to raise the priority of a command. Refer to page 734 for more information on the nice builtin and the nice utility, which is available from bash.


Allows you to log out without terminating processes running in the background. Some systems are set up to do this automatically. Refer to page 736 for information on the nohup builtin and the nohup utility, which is available from bash.


Causes the shell to notify you immediately when the status of one of your jobs changes (page 271).


Controls what action an interrupt causes within a script (page 371). See "trap: Catches a Signal" on page 493 for information on the equivalent command in bash.


Removes a directory from the directory stack (page 274).


Displays all environment variable names and values.


Changes the working directory and places the new directory at the top of the directory stack (page 274).


Re-creates the internal tables used by the hash mechanism. Whenever a new instance of tcsh is invoked, the hash mechanism creates a sorted list of all available commands based on the value of path. After you add a command to a directory in path, use rehash to re-create the sorted list of commands. If you do not, tcsh may not be able to find the new command. Also refer to hashstat (page 379) and unhash (page 381).


Takes two arguments a count and simple command (no pipes or lists of commands) and repeats the command the number of times specified by the count.


Executes a command at a specified time. For example, the following command causes the shell to print the message Dental appointment. at 10 AM:

tcsh $ sched 10:00 echo "Dental appointment."

Without any arguments, sched prints the list of scheduled commands. When the time to execute a scheduled command arrives, tcsh executes the command just before it displays a prompt.


Declares, initializes, and displays local variables (page 355).


Declares, initializes, and displays environment variables (page 355).


Analogous to the bash shift builtin (page 483). Without an argument, shift promotes the indexes of the argv array. You can use it with an argument of an array name to perform the same operation on that array.


Executes the shell script given as its argument: source does not fork another process. It is similar to the bash . (dot) builtin (page 259). The source builtin expects a TC Shell script so no leading #! is required in the script. The current shell executes source so that the script can contain commands, such as set, that affect the current shell. After you make changes to your .tcshrc or .login file, you can use source to execute it from the shell and thereby put the changes into effect without logging off and on. You can nest source builtins.


Stops a job or process that is running in the background. The stop builtin accepts multiple arguments.


Stops the current shell and puts it in the background. It is similar to the suspend key, which stops jobs running in the foreground.


Executes the command that you give it as an argument. It displays a summary of time-related information about the executed command, according to the time shell variable (page 364). Without an argument, time displays the times for the current shell and its children.


Identifies or changes the access permissions that are assigned to files you create (page 810).


Removes an alias (page 347).


Turns off the hash mechanism. See also hashstat (page 379) and rehash (page 380).


Removes limits (page 379) on the current process.


Removes a variable declaration (page 355).


Removes an environment variable declaration (page 355).


Causes the shell to wait for all child processes to terminate. When you give a wait command in response to a shell prompt, tcsh does not display a prompt until all background processes have finished execution. If you interrupt it with the interrupt key, wait displays a list of outstanding processes before tcsh displays a prompt.


When given the name of a command as an argument, locates all occurrences of the command and, for each, tells you whether it is an alias, a builtin, or an executable program in your path.


Similar to where but reports on only the command that would be executed, not all occurrences. This builtin is much faster than the Linux which utility and knows about aliases and builtins.

Chapter Summary

Like the Bourne Again Shell, the TC Shell is both a command interpreter and a programming language. The TC Shell, which is based on the C Shell that was developed at the University of California at Berkeley, includes popular features such as history, alias, and job control.

You may prefer to use tcsh as a command interpreter, especially if you are familiar with the C Shell. You can use chsh to change your login shell to tcsh. However, running tcsh as your interactive shell does not cause tcsh to run shell scripts; they will continue to be run by bash unless you explicitly specify another shell on the first line of the script or specify the script name as an argument to tcsh. Specifying the shell on the first line of a shell script ensures the behavior you expect.

If you are familiar with bash, you will notice some differences between the two shells. For instance, the syntax you use to assign a value to a variable differs and tcsh allows SPACEs around the equal sign. Both numeric and nonnumeric variables are created and given values using the set builtin. The @ builtin can evaluate numeric expressions for assignment to numeric variables.


Because there is no export builtin in tcsh, you must use the setenv builtin to create an environment (global) variable. You can also assign a value to the variable with the setenv command. The command unset removes both local and environment variables, whereas the command unsetenv removes only environment variables.


The syntax of the tcsh alias builtin is slightly different from that of alias in bash. Unlike bash, the tcsh aliases permit you to substitute command line arguments using the history mechanism syntax.

Most other tcsh features, such as history, word completion, and command line editing, closely resemble their bash counterparts. The syntax of the tcsh control structures is slightly different but provides functionality equivalent to that found in bash.


The term globbing, a carryover from the original Bourne Shell, refers to the matching of strings containing special characters (such as * and ?) to filenames. If tcsh is unable to generate a list of filenames matching a globbing pattern, it displays an error message. This behavior contrasts with that of bash, which simply leaves the pattern alone.

Standard input and standard output can be redirected in tcsh, but there is no straightforward way to redirect them independently. Doing so requires the creation of a subshell that redirects standard output to a file while making standard error available to the parent process.



Assume that you are working with the following history list:

 37 mail alex 38 cd /home/jenny/correspondence/business/cheese_co 39 less letter.0321 40 vim letter.0321 41 cp letter.0321 letter.0325 42 grep hansen letter.0325 43 vim letter.0325 44 lpr letter* 45 cd ../milk_co 46 pwd 47 vim wilson.0321 wilson.0329 

Using the history mechanism, give commands to

  1. Send mail to Alex.

  2. Use vim to edit a file named wilson.0329.

  3. Send wilson.0329 to the printer.

  4. Send both wilson.0321 and wilson.0329 to the printer.


How can you display the aliases currently in effect? Write an alias named homedots that lists the names (only) of all invisible files in your home directory.


How can you prevent a command from sending output to the terminal when you start it in the background? What can you do if you start a command in the foreground and later decide that you want it to run in the background?


What statement can you put in your ~/.tcshrc file to prevent accidentally overwriting a file when you redirect output? How can you override this feature?


Assume that the working directory contains the following files:

 adams.ltr.03 adams.brief adams.ltr.07 abelson.09 abelson.brief anthony.073 anthony.brief azevedo.99 

What happens if you press TAB after typing the following commands?

  1. less adams.l

  2. cat a

  3. ls ant

  4. file az

    What happens if you press CONTROL-D after typing the following commands?

  5. ls ab

  6. less a


Write an alias named backup that takes a filename as an argument and creates a copy of that file with the same name and a filename extension of .bak.


Write an alias named qmake (quiet make) that runs make with both standard output and standard error redirected to the file named make.log. The command qmake should accept the same options and arguments as make.


How can you make tcsh always display the pathname of the working directory as part of its prompt?

Advanced Exercises


What lines do you need to change in the Bourne Again Shell script command_menu (page 462) to turn it into a TC Shell script? Make the changes and verify that the new script works.


Users often find rm (and even rm i) too unforgiving because it removes files irrevocably. Create an alias named delete that moves files specified by its argument(s) into the ~/.trash directory. Create a second alias named undelete that moves a file from the ~/.trash directory into the working directory. Put the following line in your ~/.logout file to remove any files that you deleted during the login session:

 /bin/rm -f $HOME/.trash/* >& /dev/null 

Explain what could be different if the following line were put in your ~/.logout file instead:

 rm $HOME/.trash/* 


Modify the foreach_1 script (page 374) so that it takes the command to exec as an argument.


Rewrite the program while_1 (page 375) so that it runs faster. Use the time builtin to verify the improvement in execution time.


Write your own version of find named myfind that writes output to the file findout but without the clutter of error messages, such as those generated when you do not have permission to search a directory. The myfind command should accept the same options and arguments as find. Can you think of a situation in which myfind does not work as desired?


When the foreach_1 script (page 374) is supplied with 20 or fewer arguments, why are the commands following toomany: not executed? (Why is there no exit command?)

     < Day Day Up > 

    A Practical Guide to LinuxR Commands, Editors, and Shell Programming
    A Practical Guide to LinuxR Commands, Editors, and Shell Programming
    ISBN: 131478230
    EAN: N/A
    Year: 2005
    Pages: 213 © 2008-2017.
    If you may any questions please contact us: