. cshrc and . login file

Most users run the C-shell ‘/bin/csh' as their login environment, or these days, prefer­ably the `tcsh' which is an improved version of csh. When a user logs in to a UNIX system the C-shell starts by reading some files which configure the environment by defining variables like path.

  • The file .cshrc' is searched for in your home directory. i.e. ‘~/ . cshrc’. If it is found, its contents are interpreted by the C-shell as C-shell instructions, before giving you the command prompt.

  • If and only if this is the login shell (not a sub-shell that you have started after login) then the file'/.login' is searched for and executed.

With some thought, the ‘.login’ file can be eliminated entirely, and we can put every-­thing into the .cshrc file. Here is a very simple example ‘.cshrc’ file.

     # .cshrc - read in by every csh that starts.

Defining variables with set, setenv

We have already seen in the examples above how to define variables in C-shell. Let's formalize this. To define a local variable - that is, one which will not get passed on to programs and sub-shells running under the current shell, we write

        set local = "some string"
        set myname ="whoami"

These variables are then referred to by using the dollar '$' symbol. i.e. The value of the variable 'local' is ‘$local’.

          echo $local $ myname

Global variables, that is variables which all sub-shells inherit from the current shell are defined using `setenv'

        setenv GLOBAL "Some other string"
        setenv MYNAME "who am i"

Their values are also referred to using the '$' symbol. Notice that set uses an ‘=’ sign while `setenv' does not.Variables can be also created without a. value. The shell uses this method to switch on and off certain features, using variables like `noclobber and `noglob'. For instance

      nexus% set flag
      nexus% if ($?flag) echo 'Flag is set!' Flag is set!
      nexus% unset flag
      nexus% if ( $?flag ) echo 'Flag is set!'
      nexus%

The operator '$?variable' is 'true' if variable exists and 'false' if it does not. It does not matter whether the variable holds any information.

The commands 'unset' and `unsetenv' can be used to undefine or delete variables when you don't want them anymore.

Arrays

A useful facility in the C-shell is the ability to make arrays out of strings and other vari­ables. The round parentheses ' ( )' do this. For example, look at the following commands.

      nexus% set array =( a b c d )
      nexus% echo $array[1]
      a
      nexus% echo $array[2]
      b
      nexus% echo $array[$#array]
      d
      nexus% set noarray = ( "a b c d" )
      nexus% echo $noarray[1]
      abcd
      nexus% echo $noarray[$#noarray]
      abcd

     The special operator ‘$#’ returns the number of elements in an array. This gives us simple way of finding the end of the array. For example

                             nexus% echo $#path  
                             23

‘linux tee’ and ‘script’

Occasionally you might want to have a copy of what you see on your terminal sent to a file. 'tee' and 'script' do this. For instance,         

          find / -type 1 -print | tee myfile

sends a copy of the output of 'find' to the file `myfile'. 'tee' can split the output into as many files as you want:         

          command | tee file1 file2 . . . .

You can also choose to record the output an entire shell session using the 'script' command.

     nexus% script mysession
       Script started, file is mysession
       nexus% echo Big brother is scripting you
        Big brother is scripting you
       nexus% exit
     exit

Script done, file is mysession

The file mysession. is a text file which contains a transcript of the session.

Subshell ( )

The C-shell does not allow you to define subroutines or functions, but you can create a local shell, with its own private variables by enclosing commands in parentheses.

          #!/bin/csh
          cd /etc
               ( cd /usr/bin; ls * ) > myfile
          Pwd

This program changes the working directory to /etc and then executes a subshell which inside the brackets changes directory to /user/bin and lists the files there.The output of this private shell are sent to a file ‘myfile’.At the end we print out the current working directory just to show that the ‘cd’ command in brackets had no effect on the main program.

Tests and conditions

No programming language would be complete without tests and loops. C-shell has two kinds of decision structure: the 'if ..then..else' and the 'switch' structure. These are closely related to their C counterparts. The syntax of these is

     If ( condition )
                 command
     If( condition) then
                 Command
                 Command..
     Else
                 Command
                 Command..
     Endif
     Switch ( string)
                 Case one:
                               Commands
                               Breaksw
                 Case two:
                               Commands
                               Breaksw
                 .............
     endsw

We shall consider some examples of these statements in a moment, but first it is worth listing some important tests which can be used in 'if' questions to find out information about files.

                    '-r file'      True if the file exists and is readable

                    '-w file'          True if the file exists and is writable

                    '-x  file'      True if the file exists and is executable

                    ‘-e  file'      True if the file simply exists

                    '-z  file'       True if the file exists and is empty

                    '-f  file'       True if the file is a plain file

                    '-d  file'       True if the file is a directory

The simplest way to learn about these statements is to use them, so we shall now I. at some examples.

     #!/bin/csh –f
     # Safe copy from <arg[1]> to <arg [2]>
     if ($#argv != 2) then
             echo "Syntax: copy <from-file> <to-file>" 
             exit 0
     endif
        if ( -f $argv[2] ) then
             echo "File exists. Copy anyway?"
             switch ( $< )       # Get a line from user
                         case y:
                                breaksw   
                         default:
                                echo "Doing nothing!"
                                exit 0
             endsw
        endif
        echo -n "Copying Sargy DJ to $argy [2] ..." 
        cp $argv[1] $argv[2]
        echo done

This script tries to copy a file from one location to another. If the user does not type exactly two arguments, the script quits with a message about the correct syntax. Otherwise it tests to see whether a plain file has the same name as the file the user wanted to copy to. If such a file exists, it asks the user if he/she wants to continue before proceeding to copy.

Loops in csh and csh foreach

The C-shell has three loop structures: 'repeat', 'while' and `foreach'. We have already seen some examples of the `foreach' loop.

The structure of these loops is as follows

     repeat number-of-times command
     while ( test expression )
          commands
     end
     foreach control-variable ( list-or-array )
          commands
     end

The commands 'break' and `continue' can he used to break out of the looms at any time. Here are some examples.

repeat 2 echo "Yo!" I write mark

      This sends the message "Yo!" to mark's terminal twice.

            repeat 5 echo 'echo "Shutdown time! Log out now" I wall ; sleep 30' ; halt:

This example repeats the command 'echo Shutdown time...' five times at 30 second intervals, before shutting down the system. Only the superuser can run this command! Note the strange construction with 'echo echo'. This is to force the repeat command to take two shell commands as an argument. (Try to explain why this works for yourself.)

Input from the user

# Test a user response

       echo "Answer y/n (yes or no)"
       set valid = false
       while ( $valid == false )
            switch ( $< )
                        case y:
                              echo "You answered yes" set valid = true
                              breaksw
                        case n:
                              echo "You answered no" set valid = true
                              breaksw
                        default:
                              echo "Invalid response, try again" breaksw
             endsw
        end

Notice that it would have been simpler to replace the two lines         

            set valid - true breaksw

by a single line 'break'. breaksw' jumps out of the switch construction, after which the `while' test fails. 'break' jumps out of the entire while loop.