Introduction to C Shell

alt

Every Programmer C shell is a command language interpreter created by Bill Joy at the University of California at Berkeley. It is the standard shell, which is provided with BSD 4.1 and BSD 4.2 versions of UNIX. You can invoke the C shell by typing csh at the command prompt, just as sh is the name of the program for Bourne shell.

  • The C shell has two main advantages over Bourne shell:
  • The C shell provides a command history feature that allows rerunning (and altering) previous commands. It is so because C shell keeps track of all commands issued at the command line. It processes job control system effectively that allows processes to be moved from foreground to background or vice versa. No doubt, it would save your time on the typing work.
  • This history feature is similar to DosKey in MS-DOS environment.
  • The C shell provides an aliasing of commands. By using aliasing facility, you can set up shorthand notations for commands. Now you don’t need to remember lengthy commands in this shell. You can simply type the short alias at the command line, instead of typing the full name of the command.

Anyhow whatever may be the difference between the C shell and the Bourne shell, both have many common features, such as:

  • Shell variables
  • I/O redirection
  • Filename expansion
  • Command substitution
  • Programmability

However the concept of shell variable is same in the Bourne shell and C shell, but the C shell handles these variables somewhat differently.

  • We know that when you log in a Bourne shell version of UNIX system, it creates a sh process for you to interpret your commands. Similarly when you log in a C shell version of UNIX system, it creates a csh process for you to interpret your commands. Typically the C shell displays a % prompt instead of $ prompt of the Bourne shell.
  • You can also create a sub-shell of either type. If you want to create a Bourne shell then just type sh and for C shell you type csh. But either type of sub-shell is terminated by pressing Ctrl and d keys simultaneously. Note that the login shell is typically terminated by the logout command.
  • If you want to know your login shell then check the contents of /etc/passwd file. You can invoke one type of shell even if your login shell is different. It means that if your login shell is csh, you still invoke the Bourne shell by typing sh.


Shell Variables

  • The shell variables are an integral part of shell programming. The shell program uses shell variables to store and manipulate information within it. Therefore a shell variable is a name associated with a value. You may create any number of variables.
  • Like a Bourne shell variable, a C shell variable name must begin with either a letter (uppercase or lowercase) or an underscore (_) and followed by any combination of letters, underscore characters or numeric characters.
  • The shell variable’s names should be of any reasonable length. Note that no commas or blanks are allowed within a shell variable name.

For example,

  • area
  • _flag
  • file20
  • out_file

Like Bourne shell, the C shell provides two types of shell variables:

  1. System Shell Variables
  2. User-defined Shell Variables


System Shell Variables

The variables, which are defined by the UNIX operating system for its own use, are called as system shell variables. You can use the system shell variables and can also assign different values to these system variables.

The complete list of all system variables and their respective values can be listed by using the set command as:

% set

Some of the commonly used system variables are as:

home, path, term, user, exinit, logname, mail, pwd, shell and so on.

The meanings of these variables are already defined in the Bourne shell.


User-defined Shell Variables

The variables which are created by the user for its sake of convenience are called as user-defined shell variables. The user-defined shell variables can be of any reasonable length. The user-defined shell variables are again of two types:

  1. Regular variables
  2. Environment variables


Regular Variables

Regular variables are local variables, which are set by using the set command. For example, the statement

% set num=10

defines a regular variable num, and has assigned a value “10” to it. Unlike the Bourne shell, the C shell permits spaces as:

% set num = 10

But you can use the value of a shell variable in the same way as you have in the Bourne shell; just prefixing a $ sign with the variable num as:

% echo $num

10

%

 

Note that all shell variables are treated as string variables. Here the “10” is treated as a string of characters ‘1’ and ‘0’.

You can remove the definition of a shell variable by using the unset command as:

% unset num

You can also assign a string of more than one word to a regular shell variable using single quotes or double quotes.

% set name = ‘Suman Sagar’            using single quotes

% echo My names is $name.

My name is Suman Sagar

% set name = “Suman Sagar”          using double quotes

% echo My names is $name.

My name is Suman Sagar

 

You can also achieve the same

% set name = (Suman Sagar)            using parentheses

% echo My names is $name.

My name is Suman Sagar  

 

A shell variable which has been defined but has not been given any value is known as a null variable. Following are the ways of creating a null variable

% set name

% set name=‘ ’

% set name=“ ”  

 

When you echo a null variable, only a blank line would appear on the screen.

You can also access the individual words in a string of multi words value to a shell variable as:

% echo ${name[2]} 

Sagar

% echo ${name[2]}, $name[1]

Sagar Suman

The only necessary condition in this is that the string should be enclosed in parentheses; instead of single quotes or double quotes. You can also count number of words in a shell variable as:

% echo ${#name} 

2

You can also include a range of words by using a hyphen as:

%set text = (A man without patience is a lamp without oil.)

% echo ${text[2-7]}  

 

man without patience is a lamp

If you omit the first number of ranges as:

% echo ${text[-7]} 

then the missing number is assumed to be 1. Thus the above statement would display :

A man without patience is a lamp

On the other hand, if you omit the last number then it is supposed to be the total number of words. Thus the following statement

% echo ${text[7-]} 

would display lamp without oil.

You can display the list of all current regular shell variables and their values by using the set command as:

% set 

All regular variables are local to the shell in which they are defined. They are not available to sub-shells. Unfortunately, the C shell has no export command. But thanks Bill Joy, he added the setenv command to make a variable global.


Environment Variables

The variables which are created by a user in a shell and known to all sub-shells are known as environment variables. Here you may think that environment variables are similar to export variables. But it is not true.

In an exported variable if you make any change in its value in a child shell then this changed value would not be reflected back to a parent shell. On the other hand, if you make any change in the value of an environment variable then it would be reflected in back to a parent shell.

Environment variables are assigned as:

setenv shell_varaible value 

For example,

% setenv name Suman

% echo $name

Suman

%  

 

Note that you should not use an equal sign in the definition of an environment variable. Here you have used the echo command to display the value of an environment variable. But suppose you have a regular variable of the same name, but different values as:

% setenv name Suman

% set name = Sagar  

 

then what do you expect the output of the following echo command

% echo $name 

Suman or Sagar. Here the output would be Sagar. It is because whenever there is a conflict between a regular variable and an environment variable, it is the regular variables who wins the race. Therefore if you want to display the value of an environment varaible then use the printenv command as:

% setenv name Suman

% set name = Sagar

% echo $name

Sagar

% printenv name

Suman

%  

 

Note that the value of an environment variable is displayed without a $ prefix in the printenv command. Thus the printenv command displays the value of all currently defined environmental variables.

If you want to remove an environment variable definition then use the unsetenv command as:

% unsetenv name 


Variable Modifiers

Variable modifiers are used to modify the interpretation of a regular shell variable. The C shell provides various variable modifiers. Some useful variable modifiers are listed below:

  • :r             it returns the variable’s root and remove a trailing extension
  • :t             it returns the variable tail and removes all leading pathnames.
  • :e             it returns the variable’s extension
  • :h            it returns the variable’s header
  • :gr           it returns all roots
  • :ge           it returns all extensions
  • :gh          it returns all headers
  • :gt           it returns all tails


You can used these variables modifiers by placing them at the end of a variable name. You can understand the significance of some of these variable modifiers as:

% set userfile = /usr/user2/project/report.txt

% echo $userfile

/usr/user2/project/report.txt

% echo $userfile :r

/usr/user2/project/report

% echo $userfile :t

report.txt

% echo $userfile :e

txt

% echo $userfile :h

/usr/user2/project/

 

One should remember that never try to use these modifiers on environment variables.


Shell Script

alt

As you have read in the Bourne shell that shell scripts are just shell programs having a sequence of commands in them. In other words, you can say that a shell script is a file of UNIX commands that tells the shell what to do.

A shell script also gives an elegant way to save and use a frequent combination of commands.

For example, if you want to display the list of all login users, followed by a list of all files in the current working directory then you would write a shell script as:

who

date

Let the name of this script is csscript1. Now you can run this script as:

% csh csscript1

Mon Oct 11 09:11:15 IST 1999

aa1         tty2         Oct 11    07:15

aa4         tty3a      Oct 11    07:19

amit        tty3d      Oct 11    09:33

summy     tty4         Oct 11    10:11

%


You can also execute it directly at command prompt as:

$ csscript1 

But like Bourne shell, the default permission of a newly created file in C shell is 644 and it does not allow you to execute it. Therefore it is necessary to firstly change its file permissions as:

% chmod u+x csscript1

or

% chmod 744 csscript1  

 

and then you can use it at command prompt directly as:

% csscript1

Mon Oct 11 09:11:15 IST 2009

aa1         tty2         Oct 11    07:15

aa4         tty3a      Oct 11    07:19

amit        tty3d      Oct 11    09:33

summy  tty4         Oct 11    10:11

%

Note that here it is sh, not csh, which executes this later versions. No doubt it is due to the compatibility with the Bourne shell that executable  shell scripts in the C shell are run by the sh unless the script begins with a # symbol. However in former case, that is

% csh csscript1 

the shell script is run by the C shell. If you want to make the executable script a csh-run script then start it off with a comment as:

# C shell script1

who

date  

 

On contrary to this if you have a Bourne shell script with # markd comments then it is necessary either to remove the commands or run the script using sh as:

% sh anyscript 

Now let us see another script in which we accept the input from the keyboard and display the output to the monitor. We all know that the Boune shell provides a read command to receive input from the standard input. Unfortunately the C shell does not provide any such command. The C shell provides $< to indicate that the input is to be taken form the shell’s standard input.

Like Bourne shell, the C shell uses echo command to display the information.

# C shell script2

# Usage: csscript2

echo What is your name\?

set name=$<

echo What is your age\?

set age=$<

echo Hello $name. You are $age years old.

 

Like csscript1, csscript2 too has the default permissions 644. So firstly change its file permissions to 744 and execute it at the shell prompt as:

% csscript2

What is your name?

Shrey

What is you age?

2

Hello Shrey. You are 2 years old.

%

 

I know that you must have noticed the ‘\’ just before the question mark ‘?’ at the end of first and second echo statement in the csscript2. It is because we all know that the ‘?’ symbol is metacharacter which if not preceded by a ‘\’ represents for all files in the current working directory whose names are one character long. If you want to treat the symbol ‘?’ as an ordinary character then it is necessary to precede it by a backslash as ‘\’.


Command Line Substitution

The C shell provides the shell variable argv in which it stores the command line arguments of a shell script. For example, the parameter

$#argv 

represents the total number of arguments. If you have multiple arguments then you can access the separate arguments by using the break notation. Let you have 10 arguments at command line and want to access the 5th argument then you must type

$argv[5] 

Following shell script illustrates this concept.

# C shell script3

# Usage: csscript3

echo Total number of arguments $#argv

echo The first argument is $argv[1]

echo The last argument is $argv[$#argv]

echo The first through fifth argument is $argv[1-5]

echo The sixth through tenth argument is $argv[6-10]

 

Make this script executable and run it as:

% csscript3 Imagination is useful only as long as it remains practical.

Total number of arguments 10

The first argument is Imagination

The last argument is practical.

The first through fifth argument is Imagination is useful only as

The sixth through tenth argument is long as it remains p.

%

 

To preserve compatibility with the Bourne shell, you can also use $1, $2, $3,…and so on, notation of the Bourne shell in the C shell. Therefore, $1 is equivalent to $argv[1], $2 is equivalent to $argv[2], and so on. On the same track, $* is the same as $argv[*]

Let us see some other useful command line parameters.

$0           the name of the shell script

$$           process number of current shell

$?num     returns if num is set; 0 if num is not set

$status    returns the status of the last command

$<           reads a line from standard input

$?0         returns 1 if input filename is known; 0 if not


C Shell Metacharacters

Shell metacharacters are special characters to which special meaning has been assigned by the UNIX system. The details of these shell metacharacters are already discussed in Bourne shell.

Here we will only summarize them.

Filename Expansion Metacharacters

  • ?              match any one character
  • *              match any combination of characters (including the null character and excluding an initial period)
  • [list]         match any one character from the list
  • [!list]        match any one character except those enclosed in the lsit


Special Shell Metacharacters

  • $#           total number of positional parameters
  • $0           name of the command being executed
  • $*           list of all shell arguments
  • $@          same as $*, but yields each argument separately when enclosed in double quotes
  • $!            Process ID of the last background command
  • $$           Process ID of the current command
  • $-            current shell setting
  • $?            The exit status of last executed command

Now we will see – how the expressions are evaluated in C shell


Expressions

The C shell expressions involve operators and operands just like C language. The value of an expression can be assigned to a shell variable via the @ command. The @ command allows you to perform you to perform numerical manipulations in the expression.

The @ command is similar to the set command, except it assigns the value of an expression rather than a word to a variable. It means that you can not assign a word to a shell variable by using the @ command. The C shell provides five arithmetic operators:

Arithmetic Operators

Symbols                      Meaning

 

* / %                        Multiplication, integer division, remainder

+  –                           Addition, subtraction


Now let us see some simple shell programs.

# C shell script4

# Usage: csscript4

set name = Shery

@ age = 24

@ salary = 100000

echo $name $age $salary

 

When you execute this script, you get the following output….

% csscript4

Shrey 24 100000

%

Now let us write a script that displays the reverse of a five digit number.

# C shell script5

# Usage: csscript5

echo “Enter a number: \c”

set n = $<

@ a = n % 10

@ n = n / 10

@ b = n % 10

@ n = n / 10

@ c = n % 10

@ n = n / 10

@ d = n % 10

@ n = n / 10

@ e = n % 10

@ rev = a * 10000 + b * 1000 + c * 100 + d * 10 + e

echo The reverse of a five digit number is: $num

 

The output of this program is….

% csscript5

Enter a number: 12345

The reverse of a five digit number is: 54321

%

The C shell also provides the increment operator (++) and decrement operator (--) of C language.


Following program illustrates the behavior of these two operators.

# C shell script6

# Usage: csscript6

@ a = 20

@ b = 10

@ a++

@ b- -

echo $a $b

@ a++

@ b- -

echo $a $b

 

And here is the output of this script….

% csscript6

21 9

22 8

%

Assignment Operators

The C shell provides following types of assignment operators.

Symbol          Meaning

 

=                  Assigning value

+= -=           Reassign after addition/subtraction

*= /= %=   Reassign after multiplication/division/remainder


On the similar track you can use arithmetical assignment operators as:

# C shell script7

# Usage: csscript7

@ a = 20

@ b = 10

@ a += b

echo $a

@ b -= 4

echo $b

@ a *= b

echo $a

@ a /= 9

echo $a

@ a %= 3

echo $a

 

The output of this script is as….

% ssscript7

30

6

180

20

2

%

Like Bourne shell, the C shell also provides programming constructs, such as if – else, the while loop, the foreach loop, and the repeat loop.

The if Structure

We know that, the instructions in a program are executed sequentially. But sometimes we need to do one thing under some circumstances and a different thing otherwise. To accomplish this, the C shell provides the if structures to control the order of execution of the commands in the program. Let us begin with the simple if structure.

The simplest form of if command is

if (expression)       command


Here unlike the Bourne shell’s if, the expression is enclosed within parentheses. If the result of expression is true then the command is executed; otherwise not. And the command must be a simple and single command. You can not use pipes and compound commands.

If you want to use several commands then the C shell provides the if–then-endif structure. Its syntax is

if (expression) then

command1

command2

….

endif

 

 

Here if the expression results in true, the commands enclosed between the keyword then and endif are executed. It is necessary to place the if – then portion on one line, the endif on another line and the set of commands in between these two lines.

Let us see how to use this structure.

# C shell script8

# Usage: csscript8

echo What is your age\?

set age = $<

if ($age <= 20) then

echo You have not yet grown up.

echo Please take a ThumsUP.

endif

 

A sample run of this script is….

% csscript8

What is your age?

16

You have not yet grown up.

Please take a ThumsUP.

%

 

 

Here we have seen that if the expression results in true, the if statement executes a command or a set of commands. It does nothing when the expression is false. If you want to perform something even when the expression results in false, then you can use another form of if structure, that is if-then-else-endif.

Here is the general form of this if structure

if (expression) then

command

command

….

else

command

command

….

endif

 

Let us rewrite csscript8 in which we include the else part.

# C shell script9

# Usage: csscript9

echo What is your age\?

set age = $<

if ($age <= 20) then

echo You have not yet grown up.

echo Please take a cold drink.

else

echo You can drink Beer.

endif

 

A sample run of this script is….

% csscript9

What is your age?

16

You have not yet grown up.

Please take a cold dring..

% sscript9

What is your age?

22

You can drink Beer.

%

Nested if–elses Structure

 

Like C language, the C shell also provides the facility of using nested ifs, that is defining if-then-else-endif structure within either the if body or the else body.

The syntax of nesting if structure is

if(expression1) then

if (expression2) then

command1

command2

else

command3

command4

endif

else

command5

command6

endif

or

if(expression1) then

command1

command2

else

if (expression2) then

command3

command4

else

command5

command6

endif

endif

 

 

In the former case, the second if structure is nested in the first if statement whereas in later form, the second if structure is nested in the first else statement. Note that there is no limit on how deeply the ifs and elses can be nested.

Following program illustrates the usage of nested ifs.

# C shell script10

# Usage: csscript10

echo What is your age\?

set age = $>

if ($age <= 5) then

echo You are a lovely kid.

else

if ($age >5 && $age <= 10) then

echo You are growing up.

else

if ($age >10 && $age <= 20) then

echo You have not yet grown up.

else

echo Nice to see a young guy.

endif

endif

endif

 

Here you have used logical && operator to combine two condition into one.

The output of this program is

% csscript10

 

What is your age?

23

Nice to see a young guy.

% csscript10

What is your age?

13

You have not yet grown up.

% csscript10

What is your age?

4

You are a lovely kid.

%

 

Here we have used multiple endifs. You can also avoid typing multiple endifs by typing else if on just one line as shown below:

# C shell script11

# Usage: csscript11

echo What is your age\?

set age = $<

if ($age <= 5) then

echo You are a lovely kid.

else if ($age >5 && $age <= 10) then

echo You are growing up.

else if ($age >10 && $age <= 20) then

echo You have not yet grown up.

else

echo Nice to see a young guy.

endif

 

The output of this shell program is similar to csscript10.

Thus nested if-elses offers two or more choices. Here if the first expression is true then the if block is executed and control reaches the endif. If the first expression is false then the control goes to the first else-if block. In this again the expression is evaluated. If it is true then the command following it is executed otherwise the control reaches at next else-if. This process continues for other elseifs. If all the expressions are false then the control reaches the else block and executes the command(s) within it.


File Testing Expressions

Like Bourne shell, the C shell also provides several options for checking the status of a file. These are listed as:

-r file       true if file exist and is readable

-w file     true if file exist and is writeable

-x file      true if file exist and is executable

-f file      true if file exist and not a directory

-d file      true if file exist and is a directory

-c file      true if file exist and is a character special file

-b file      true if file exist and is a block special file

-s file      true if file exist and has a size greater than 0

-k file      true if file exist and its sticky bit is set

With the help of these options, you can easily find out whether the specified file is an ordinary file, a directory or whether it grants read, write or execute permissions and so on.

Here is a more concrete example.

# C shell script12

# Usage: csscript12

echo “Enter a filename: \c”

set filename = $<

if ( -d $filename) then

echo This is an ordinary file.

else if ( -f $filename)

echo This file is a directory file.

else

echo What did you enter\?

endif

 

On executing this script, you get the following output….

% csscript12

Enter a filename: bin

This file is a directory file.

% csscript12

Enter a filename: Jana

What did you enter?

%

 

The switch Structure

No doubt, nested ifs may offer multiple choices. But it is the switch structure that offers an efficient way to compare a value to a list of choice and to take the corresponding action. The behavior of the switch structure is similar to the case structure of the Bourne shell.

The general form of the switch structure is

switch (value)

 

case choice1 :

command

command

….

breaksw

case choice2 :

command

command

….

breaksw

case choice3 :

command

command

….

breaksw

default :

command

command

….

breaksw

endsw

The syntax of the switch structure closely looks like the switch of the C language.

Here the value is matched with successive case labels (choice1, choice2 and so on) until it finds a match. Whenever it finds a match, it executes  the commands belong to that particular case label. If there is no match, the program executes the commands of the default label. Here the keyword breaksw is used to take control out of switch structure as soon as it executes all the commands from that match label. If you don’t use the breaksw the all the commands from that matching label to endsw are executed.

Let us now put these concepts to a practical stint. Here is the program that illustrates the usage of the switch structure.

# C shell script13

# Usage: csscript13

echo “Enter a character from a to d : \c”

set char = $<

switch ($char)

case a:   echo You have entered a.

breaksw

case b:   echo You have entered b.

breaksw

case c:    echo You have entered c.

breaksw

case d:   echo You have entered d.

breaksw

default:  echo Please enter a to d.

breaksw

endsw

 

Here the program asks the user to enter a character and then determines whether you have entered a, b, c, d or something else.

The output of this program is….

% csscript13

Enter a character from a to d : a

You have entered a.

% csscript13

Enter a character from a to d : d

You have entered d.

% csscript13

Enter a character from a to d : g

Please enter a to d.

%

Note that the case labels may be in any order you want. You can place case label b before a, d before b, or in any order. Here is the example of scrambled case order.

# C shell script14

# Usage: csscript14

echo “Enter a character from a to d : \c”

set char = $<

switch ($char)

case b:   echo You have entered b.

breaksw

case d:   echo You have entered d.

breaksw

case c:    echo You have entered c.

breaksw

case a:   echo You have entered a.

breaksw

default:  echo Please enter a to d.

breaksw

endsw

 

The output of this program is similar to earlier one.

However you are not limited to using single letters or digits. You can also use entire words as the choice labels as shown in following script.

# C shell script15

# Usage: csscript15

echo “Enter any cricketer name: \c”

set name = $<

switch ($name)

case Sachin:         echo Best Batsman

breaksw

case McGrath:     echo Best Bowler

breaksw

case Gilchrist:       echo Best Wicket Kepper

breaksw

case Cairns:          echo Best All Rounder

breaksw

case Rhodes:        echo Best Fielder

breaksw

default:                  echo Your taste is different.

breaksw

endsw

 

 

Here is some interaction with the program….

% csscript15

Enter any cricketer name: McGrath

Best Bowler

% csscript15

Enter any cricketer name: Sachin

Best Batsman

% csscript15

Enter any cricketer name: Rhodes

Best Fielder

% csscript15

Enter any cricketer name: Cronje

Your taste is different.

%

One more point to note, while suing the switch structure, that makes the default choice as the last choice. If you make it as the first choice then it would match any value and the case would not be searched any further.

If you want to know about some other options please study the Bourne shell case structure.

Logical Operators

Like Bourne shell, the C shell provides following three types of logical operators:

Symbol     Meaning

&&         AND

||              OR

!               NOT


First two operators, && and ||, allow two or more conditions in a single condition. Now let us write a script that determines whether a year is a leap or not, with the help of logical && and || operators.

# C shell script16

# Usage: csscript16

echo “Enter any year: \c”

set year = $>

if (($year%4==0)&&($year%100!=0)||($year%400==0)) then

echo $year is a leap year.

else

echo $year is not a leap year.

 

Here is the simple interaction with the program….

% sccript16

Enter any year: 1976

1976 is a leap year.

% sccript16

Enter any year: 1900

1976 is not a leap year.

% 

 


 


Like it on Facebook, Tweet it or share this article on other bookmarking websites.

No comments