csh and tcsh scripts

See shells for an introduction to the shell syntax.

There is (almost ?) no difference between the syntax of csh and tcsh statements used in scripts; the two shells differ mostly in their interactive features (such as capabilities of command completion). There are UNIX/Linux systems which contain csh but not tcsh. Every UNIX/Linux system that contains tcsh, either also contains csh, or csh could be added to it just by creating a symbolic link called csh that points to tcsh. tcsh is an extension of csh, compatible with csh. (When  tcsh is invoked through a link called csh, the tcsh notices this fact and assumes the exact behavior of csh. ???)  For these reasons most programmers write just csh scripts, not tcsh scripts.

The syntax of csh, unlike bash, is somewhat similar to that of the C language.

The first line of every csh script should be
#!/bin/csh

or
#!/bin/csh -f 

preceded by no spaces or tabs. This is more than just a comment -- this line tells the system how to call the interpreter which will execute the script. The -f option causes that the csh shell that executes the script does not read (any or user's ???) initialization files. 

Debugging
The following statements, individually or together, are useful during the development of a script:
set echo
set verbose

When the script is executed, they will cause that a trace of execution will be printed on the screen.

Whitespace
Line breaks and spaces in csh scripts do matter! If a construct you typed does not work, check again if it is formatted the same way as in the examples below.

Data
The only type of scalar data is string. There are no integers, floats, etc. Whenever we use something that looks like an integer, a string that contains decimal digits is created. There is a way to create an arithmetic context, in which integer-like strings are converted to actual integers and arithmetic operations can be performed; the result of such operations are strings containing decimal digits. Besides strings, list-arrays of strings are available.

Shell variables.
By convention names of shell variables are not capitalized."
Remember to put spaces around the = symbol.
set VARNAME = VALUE
set aa = Hello
set bb = 'Hello world'
set aa = "$aa my friend"
set outputFile = ~/csc319/out.txt
set user1 = abcd1234
set nn = 345
unset bb

The following are equivalent:
set ee     
set ee = ''

Shell list-array variables.
There are only lists of strings; there are no lists of lists -- no nested lists.
set users = ($user1 bcde2345)
set users = (root $users cdef3456 ghij7890
set $users[0] = defg4567
set numberOfUsers = $#users
set users2to4 = "$users[2-4]" 
set allUsers = "$users[*]"
set lastUser = $users[$]   # last element

Command line parameters
$0   -- the name through which the script was invoked (test what happens if you invoke a script through a symbolic link)
$1, $2, ..., $9 -- the first, second, ..., ninth parameter with which the script was invoked.
$* -- the list of all command line parameters, (excluding the name of the script).
$#argv -- the number of command line parameters. 
It is useful to use :q operation, in case if the parameters escaped contained white space.
If the user of a script wants to specify a parameter string which contains white space, every white space character must be preceded by \.
If the user  typed myscript fff\ ggg, in the script the following values would be received:
$1  would have value fff
$2 would have value ggg
$* would have value (fff ggg)
$1:q would have value 'fff ggg'
$*:q would have value ('fff ggg')

Input
Every time user presses Enter, special variable $< is updated to store one line of users input;  the line break is not a part if the string in $<.
WHAT IF USER TYPES CTRL-D ?

Output
echo
echo 'cc = $cc'
echo "cc = $cc"                        -- echo adds a line break after the string.
echo "$bb\n $cc"                      -- Use \n to specify an additional line break.
echo -n "$aa     $bb     $cc"      -- With -n, echo will not add a line break.
echo $aa > $outputFile
echo $cc >> $outputFile
echo "$nn+$nn"                        -- addition not performed.

cat << ENDLABEL                 -- this outputs all the text up to but excluding ENDLABEL.
    ...                                             You can use MESSAGE1_END, etc as the end label.
    ...                                             This feature is called a "here document"
ENDLABEL                          

String operations
There is no concatenation operator. To concatenate strings, put them one next to the other.
set newstring = aaa$string1${string2}bbb
Notice that curly braces can be used to delimit the variable name (so that the shell does not  think the variable  name is string2bbb.)
set myfile = /usr/users/abcd1234/sorter.c
set head = $myfile:h    -- gets value /usr/users/abcd1234
set tail = $myfile:t    -- gets value sorter.c   
set root = $myfile:r    -- gets value /usr/users/abcd1234/sorter
set extension = $myfile:e    -- gets value c 

Boolean expressions

$?VARIABLE -- test if VARIABLE is defined

== -- test if two strings are equal
!= -- test if two strings are different
=~ -- test if the string on the left matches the string pattern on the right (the expression can contain *, meaning "any string of 0 or more characters.")
!~ --test if the string on the left does not match the string pattern on the right

-e $file  -- test if $file exists
-d $file  -- test if $file exists and is a directory
-f $file  -- test if $file exists and is a regular file
-r $file -- test if $file exists and is readable by the current process
-w $file -- test if $file exists and is writable by the current process
-x $file -- test if $file exists and is executable by the current process

0 and empty string both serve as value false (although they are not equal); 0 is the default value for false; 1 serves as value true.
Boolean expressions can be combined using && (conjunction), || (disjunction) and ! (negation).

Integer arithmetic operations
set aa = 2+2    -- variable aa gets value '2+2'
@ aa = 2+2      -- variable aa gets value 4
@ a++              -- now, aa has value 5.
Arbitrary arithmetic expressions with +, -, *, /, ++, --, % (remainder) and parentheses are allowed.

One-line conditional statement
if (BOOLEAN-EXPESSION) COMMAND
if (-r comments.txt) cat comments.txt >> summary.txt
Notice that there are no words "then" or "end".
Notice that the statement must be on a the same line (unless line breaks are escaped).

If-then-else statement

if ( EXPR1 ) then
    ...
else if ( EXPR2 ) then
    ...
else
    ...
endif

There can be any number else-if parts.
Else-if and else parts are optional.

Switch-case statement

switch ( EXPR )
    case STRINGPATTERN1:
        ...
        ...
        breaksw
    case STRINGPATTERN2:
    case STRINGPATTERN3:
        ...
        ...
        breaksw
    default:
        ...
        ...
endsw

Foreach loop

foreach VARNAME  LIST
    ...
    ...
end

For instance:
 

set users = (aaaaa111, bbbbb222, ccccc333)
foreach user ($users)
    grep $user /etc/passwd
end

foreach file ( csc* )
    if (! -d $file) chmod o-r $file
end

While loop

while ( EXPR )
    ...
end

Other features

If you use a file pattern with a wildcard (e.g. csc*), the pattern will expand to a list of files in the present working directory whose names match the pattern.

There are no functions, procedures, methods, subroutines in csh or tcsh. Instead, one can use aliases with parameters or goto statements.

To obtain the output of a command and to process it in the script, enclose the command in back-quotes:
set fileInfo = `ls -l project.java`


C and TC shell initialization
There are login and non-login shells and interactive and non-interactive shells, as explained in the chart below. 

Users can customize their shell behavior by placing shell commands in files ~/.cshrc and ~/.login. The commands in these files are executed by new shells, as described in the chart. Executing commands in these files should is not the same as executing the files themselves -- executing the files would mean that the shell forks and spawns a child shell that executes the commands in file -- these would not initialize the parent shell. Executing commands in a file by a shell is called sourcing the file. 

  Interactive shell
(one that displays a prompt)
Non-interactive shell
(one that executes commands in a script)
Login shell
(the first shell in a new session)
sources ~/.cshrc
then sources ~/.login
sources ~/.cshrc   ??? TEST IT
Non-login shell
(any subsequent shell in a session)
sources ~/.cshrc sources ~/.cshrc  -- if specified as #!/bin/(t)csh
does not source it if specified as #!/bin/(t)csh -f

After you edit ~/.cshrc and /.login to test the changes in the login shell, you need either to logout and login again, or force the login shell to source them:

                login_shell% source ~/.cshrc

Environment variables are inherited by every child process. In particular, environment variable definitions sourced by the login shell will be known in all the subsequent interactive and non-interactive shells -- it is enough to define environment variables in ~/.login file, which is sourced only by the login shell.

Aliases and shell variables sourced by the login shell are not inherited by subsequent shells. It is recommended to place for alias and shell variable definitions in ~/.cshrc, and it is recommended to use #!/bin/(t)csh -f at the top of all csh scripts to prevent them from sourcing ~/.cshrc.

Changing shell
Your default shell is specified in your entry in file /etc/passwd
To change your default shell, use the chsh command.

Next see: Defining and redefining commands.