Unix Shell Programming Notes. Part I

UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity.
Dennis Ritchie

Shell commands can be combined in script files that perform complex actions. In this first article, a concise introduction to shell programming (focusing on the csh shell) is given. In the second part, I will provide some examples of complex scripting for different applications. For other types of shells, the reader can consult comprehensive textbooks that are listed at the end of this article.

A shell script files start with the command:

#! /bin/csh –f

the #! is the autostart command for the script shell command /bin/csh (this example use the c shell but it is the same for the other type of shells). The -f option is used to make a fast startup by not reading or executing the commands in .cshrc file(this is a setup file that is executed at the start of the shell). To execute the script file, it must be made executable using chmod and hence it can be invoked by typing the script file name on the command line:

chmod +x script

./script

SHELL VARIABLES 

    set c= 299792458

The value of a shell variable can be referenced by placing a $ before the name of the variable or the curl parenthesis enclosing it. The commands

     echo $c

     echo ${c}

will output the same value of the variable C. In the case of string variables, the curl parentheses can be used to append to the string variable other strings of characters.

EXAMPLE

set fname = prog

    set cc=1 

    rm ${fname}$cc.c

This script deletes the file ‘prog1.c’ form the current directory. Special variable attributes as :r can be used to extract root names or suffixes from file names:

EXAMPLE

set fname=prog.dat

  echo ${fname:r}

  echo ${fname:s}

it will print

     prog
     dat

Arrays of data can be defined using the list variables:

     set CONST = ( 4.148 273.15 )

and the single element assigned as

    set CONST[3] = 11.01

The number of elements in a list variable can be printed using the prefix with a #.

The command echo $#CONST will print 3.

The @ command can be used for computations. For example, if you have shell variables $X and $Y, you can set a third variable $Z to their sum by

     @Z = $X + $Y

While the commands

@ Z ++

@ Z – increment or decrement of one unit the value of Z, respectively.

SPECIAL VARIABLES

The shell reserves some of the variable names for specific purposes. One important variable is the shell variable argv. This list variable contains the arguments (parameters) that are provided to the shell script at the execution. The parameters are accessible as list elements $argv[1], $argv[2], etc. or as $1, $2, etc. The number of such arguments is $#argv.

EXAMPLE

This script evaluate an arithmetic operation between two input numbers.

#!/bin/csh -f

set val1 = $argv[1]
set val2 = $argv[2]

set result = `expr $val1 + $val2 \* $val2 - $val1 \* $val2`

echo "Result: $result"

This script performs basic arithmetic operations on two values provided as command-line arguments and then echoes the result. Here’s a breakdown of the script:

  1. #!/bin/csh -f: This line is called a shebang line and specifies that the script should be interpreted using the C Shell (csh) with the -f option, which suppresses the reading of the user’s ~/.cshrc file. It tells the system how to execute the script.
  2. set val1 = $argv[1] and set val2 = $argv[2]: These lines set the variables val1 and val2 to the first and third command-line arguments passed to the script, respectively. In Unix-like systems, command-line arguments are accessed using the $argv array, where $argv[1] represents the first argument, $argv[2] the second, and so on.
  3. set result =expr $val1 + $val2 * $val2 – $val1 * $val2`: This line calculates the result of the arithmetic expression and assigns it to the variableresult. It uses theexpr` command to perform the calculations. Here’s a breakdown of the arithmetic expression:
  1. echo "Result: $result": Finally, this line echoes the calculated result along with the text “Result:” to the standard output.

Save the script in the file named “script.csh” and execute by input two numbers separated by the operation you want to perform on them. For example, if you were to run the script with the following command:

./script.csh 5 + 3

It would output:

Result: 20

Please note that this script assumes the provided arguments are valid and does not include error checking for invalid inputs or division by zero.

Language Constructs

The c-shell script language has instructions for conditional execution (if-then-else; while), iterative execution (for-loop), a switch statement (it was used in the previous paragraph), and a goto statement:

Conditional execution statement (if-then-else)

The syntax of the if-then-else construct is

if ( expr ) simple-command

or

if ( expr ) then <command list-1>

else

<command list-2>

endif

The true or false value of the expression expr determines the execution of the commandlist1 and commandlist2, respectively. The portion of the construct enclosed in ’[’ and ’]’ is optional.

EXAMPLE

This example evaluates an arithmetic operation between two input numbers.

#!/bin/csh -f

clear
while (1)
  echo "Menu Options:"
  echo "1. Display date and time"
  echo "2. List files in the current directory"
  echo "3. View Disk Space Usage"
  echo "4. Search for Files"
  echo "5. Exit"
  echo -n "Enter your choice (1/2/3/4/5): "
  set choice = $<

  if ($choice == 1) then
    date
  else if ($choice == 2) then
    ls -l
  else if ($choice == 3) then
    df -h
  else if ($choice == 4) then
    echo -n "Enter the directory to search: "
    set search_dir = $<

    echo -n "Enter the search term: "
    set search_term = $<

    echo "Matching files in '$search_dir' for '$search_term':"
    find $search_dir -type f -name "*$search_term*" -print
  else if ($choice == 5) then
    echo "Goodbye!"
    exit 0
  else
    echo "Invalid choice. Please select a valid option (1/2/3/4/5)."
  endif
end

Description of the C Shell Script:

This C Shell script provides a simple interactive menu-driven interface that allows the user to perform various system-related tasks. Here’s a breakdown of its functionality:

  1. clear: This command clears the terminal screen to provide a clean interface for the menu.
  2. while (1): This starts an infinite loop that continues until the user selects the “Exit” option (option 5).
  3. The following lines display a menu with five options, where each option corresponds to a specific task:
  • Option 1: Display date and time
  • Option 2: List files in the current directory
  • Option 3: View disk space usage
  • Option 4: Search for files in a specified directory
  • Option 5: Exit the script
  1. echo -n "Enter your choice (1/2/3/4/5): ": This prompts the user to enter their choice by displaying a message on the screen without a newline character (-n).
  2. set choice = $<: This line reads the user’s choice (a single-digit number) from the keyboard input and stores it in the variable $choice.
  3. The script uses conditional statements (if, else if, and else) to determine the action to be taken based on the user’s choice:
  • If the user selects option 1, it displays the date and time using the date command.
  • If the user selects option 2, it lists files in the current directory using the ls -l command.
  • If the user selects option 3, it views disk space usage using the df -h command.
  • If the user selects option 4, it prompts the user to enter a directory and a search term, then uses the find command to search for files in the specified directory that match the search term.
  • If the user selects option 5, it displays a farewell message and exits the script (exit 0).
  1. If the user enters an invalid choice (a number other than 1, 2, 3, 4, or 5), the script displays an error message prompting the user to select a valid option.
  2. The loop continues, allowing the user to make multiple selections until they choose to exit the script.

In summary, this script provides a basic text-based menu interface for performing common system-related tasks and offers a simple example of interactive shell scripting in the C Shell (csh).

You can save this script to a file (e.g., menu.csh), make it executable with

chmod +x menu.csh,

and then run it as

./menu.csh

to see the menu using if-else statements in action.

The switch command

The switch command was used in the example of the previous paragraph. It is a conditional statement with multiple branches. The general form of switch is:

switch (string)

case pattern1:
   command_list1
   breaksw
   case pattern2: 
      command_list2
      breaksw
default: 
command_list

endsw

The given string str is successively matched against the case patterns that can be regular expressions. Control flow is switched to where the first match occurs.

EXAMPLE

The following script is the same as in the example given before but uses the switch command instead of the if command.

#!/bin/csh -f

while (1)
  echo "Menu Options:"
  echo "1. Display date and time"
  echo "2. List files in the current directory"
  echo "3. Exit"
  echo -n "Enter your choice (1/2/3): "
  set choice = $<

  switch ($choice)
    case 1:
      date
      breaksw
    case 2:
      ls
      breaksw
    case 3:
      echo "Goodbye!"
      exit 0
    default:
      echo "Invalid choice. Please select a valid option (1/2/3)."
  endsw
end

INSTRUCTIONS FOR ITERATIVE EXECUTION 

The while-end

The syntax of while loop construct is

      while ( expr ) commandlist

                  end

The command list will be executed until the expression “expr” is evaluated as false.

The foreach -end

The syntax of foreach loop construct is

                  foreach var ( worddlist ) commandlist

                  end

The command list is executed once for each word in the wordlist, and each time the variable var will contain the value of that word.

EXAMPLE

The following script iterates through all files with a .tif extension in the current directory and converts them to .jpg format using the convert command from the ImageMagick image manipulation software.

#! /bin/csh -f

set f = $1

foreach d (*.tif)
  echo FOUND: ${d:r}.jpg
  set f=${d:r}.jpg
  convert $d $f
end

Here’s a breakdown of the script:

  1. set f = $1: This sets the variable f to the first command-line argument, which presumably represents the output filename.
  2. foreach d (*.tif): This is a loop that iterates through all files with a .tif extension in the current directory.
  3. echo FOUND: ${d:r}.jpg: It echoes the name of each found .tif file followed by .jpg (the name of the converted file).
  4. set f=${d:r}.jpg: It sets the variable f to the name of the converted .jpg file corresponding to the current .tif file in the loop.
  5. convert $d $f: It uses the convert command to convert the current .tif file ($d) to the corresponding .jpg file ($f).

Please ensure that you have the convert command installed on your system.

In the second part of these notes, I will show more complex example of applications.

FURTHER READINGS

  1. Shelley Powers, Jerry Peek, Tim O’Reilly, Mike Loukides. Unix Power Tools, Third Edition. O’Reilly Media, Inc.; 3rd edition (October 1, 2002)
  2. David I. Schwartz. Introduction to UNIX (2nd Edition)

One thought on “Unix Shell Programming Notes. Part I

  1. Pingback: Unix C-Shell Programming Notes: Part II |

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.