---
title: C Shell Scripting
h1: C Shell Scripting
description: Tutorial on C Shell Scripting.
author: JWRR
date: January 13, 2019
theme: a
...
[View Markdown](c-shell-scripting.md)

{{ toc}}

Here are some notes on C-Shell scripts.  It's not all encompassing, but it
covers most of what I do with a shell script.  If I need to do more then I
usually switch to Perl.

<a name="pound-shebang"></a>
## Pound Shebang

The **&num;** is a pound sign, and the **&excl;** is the shebang. The
**&num;&excl;** (Pound Shebang) indicates the interpreter program that should
run the script.  This can be any of the many shell programs, Perl, PHP, Python
or even your own custom program. I'm pretty sure all Unix shells support Pound
Shebang, it's not C-Shell specific.  A C-Shell script should always start with
the following line.

```
&num;!/bin/csh
```

<a name="arguments"></a>
## C-Shell Command Line Arguments

Usually a C-Shell script has one more more commandline
arguments.  **&dollar;&num;argv** indicates the number of arguments.
This example prints a message and exits if there are less than two arguments
entered.

```
if ($#argv<2) then
   echo "Error - Not enough arguments. Script aborting."
   exit
endif
```

<a name="variables"></a>
## Set Variables

The command line arguments are stored in array **&dollar;argv**.  The first
argument is in **$argv[1]**, the second in **$argv[2]** and so on.

The **set** command assigns a value to a variable.  In this example the first
argument contains the sitename.  Variables are set to a value without
the &dollar;-sign and are accessed with the &dollar;-sign.

```
set sitename = $argv[1]
echo $sitename
```

In the following example default values are assigned to indicate what tasks
the script will do.  In this example the default is to do nothing so all
to **do** variables default to 0 (false).  The default values may be
over-ridden by command-line arguments in a subsequent example.

```
set do_backup = 0
set do_wget = 0
set do_gsutil = 0
```

## C-Shell Flow Control

<a name="foreach"></a>
### Foreach loop

You can loop through each argument using the **foreach** command.  Note the
variable **arg** does *NOT* have a $-sign in the foreach line, but it
does have a $-sign when it is used.

```
foreach arg ($argv)
 echo "argument = " $arg
end
```

<a name="if"></a>
### If Statement

When an **if** statement has only one command to execute then you can put
the **if** statement and the command on a single line.

#### IMPORTANT NOTE:
In the following example the **==** has a **' '** space on each side.  This is
needed and the script will not function correctly without these spaces. This
is an annoying quirk of the C-Shell, but it's not too significant if you
know about it... which you now do.

```
foreach arg ($argv)
   if ($arg == '1') set do_wget = 1
   if ($arg == '2') set do_backup = 1
   if ($arg == '3') set do_delete = 1
end
if ($do_wget) echo "do_wget"
if ($do_backup) echo "do_backup"
if ($do_delete) echo "do_delete"
```

If multiple commands are to be executed within the if statement then you
need **then** on the *if* line and you need *endif* at the end.

```
if ($do_wget) then
   wget -r php.${sitename}
   echo "Creating deleteme.script"
   diff -rqs php.${sitename} php.${sitename}.orig |grep ' are identical$' |sed 's#^Files \(.*\) and .*#rm -rfv \1#' > deleteme.script
endif
```

C-Shell supports the **else**.  Note, you do **NOT** need the **endif** before
the **else**. In the following example, nested **if** statements use the **-e**
file existence check to determine what files should be copied.

```
if ($do_backup) then
  if (-e php.${sitename}) then
    if (-e php.${sitename}.orig) then
      echo "Moving 'php.${sitename}' to 'php.${sitename}.backup'"
      echo "You will want to move 'php.${sitename}.backup' to 'php.${sitename}.orig' so the diff/delete_unchanged phase works"
      cp -rf php.${sitename} php.${sitename}.backup
    else
      echo "Moving 'php.${sitename}' to 'php.${sitename}.orig'"
      cp -rf php.${sitename} php.${sitename}.orig
    endif
 endif
endif
```

The following example runs a script if it exists. The **-e** file existence
check is used. The **! -e** indicates that the file does not exist.

```
if ($do_delete) then
  if ( -e deleteme.script ) source deleteme.script
  if ( ! -e deleteme.script ) echo "deleteme.script does not exist"
end if
```

Here is a list of CShell file checks that I am aware of.

```
-d file file is a directory
-e file file exists
-f file file is an ordinary file
-r file file is readable by user
-o file file is owned by user
-w file file is writable by user
-x file file is executable by user
-z file file has size 0
```

In the following example the **foreach** loop iterates through a list
of numbers.

```
foreach i (1 2 3 4)
  echo $i
end
```

The following example is another way to iterate through a range of numbers.
There are two things worth notingis this example.

* The Unix/Linux **seq first step last** command generates a sequence. This
  command is available on the command-line of most Unix/Linux shells.
* The backtick puts the stdout output of the embedded command(s) onto the
  command line.  This is also available in most Unix/Linux shells.

In the following example, the empty sub-directories in php.1, php.2,
php.3 and php.4 are found and deleted.

```
foreach i (&grave;seq 1 1 4&grave;)
  rm -rf &grave;find php.${sitename} -empty&grave;
end
```

The following example loops through a list of files returned by
glob **&ast;.txt**.  A backup is made of each file.

```
foreach file (&ast;.txt)
  cp $file $file.bck
end
```

<a name="cd"></a>
## Changing Directories in Script

The **pushd** command can be used to change into a directory and the
the **popd** command returns to the original directory after the work
is completed.

```
pushd php.${sitename}
pwd
popd
pwd
```

<a name="echo"></a>
## Show Progress

The **echo** command prints text stdout.

```
echo 'Done!'
```
