Shell Programming
Variables
A variable is nothing more than a pointer to the actual data. The shell enables you to create,
assign, and delete variables.
Variable Names
The name of a variable can contain only letters (a to z or A to Z), numbers ( 0 to 9) or the
underscore character ( _).
By convention, Unix shell variables will have their names in UPPERCASE.
The following examples are valid variable names −
_ALI
TOKEN_A
VAR_1
VAR_2
Following are the examples of invalid variable names −
2_VAR
-VARIABLE
VAR1-VAR2
VAR_A!
The reason you cannot use other characters such as !, *, or - is that these characters have a
special meaning for the shell.
Defining Variables
Variables are defined as follows −
variable_name=variable_value
For example −
NAME="Zara Ali"
Page | 1
The above example defines the variable NAME and assigns the value "Zara Ali" to it. Variables
of this type are called scalar variables. A scalar variable can hold only one value at a time.
Shell enables you to store any value you want in a variable. For example −
VAR1="Zara Ali"
VAR2=100
Accessing Values
To access the value stored in a variable, prefix its name with the dollar sign ($) −
For example, the following script will access the value of defined variable NAME and print it on
STDOUT −
#!/bin/sh
NAME="Zara Ali"
echo $NAME
The above script will produce the following value −
Zara Ali
Read-only Variables
Shell provides a way to mark variables as read-only by using the read-only command. After a
variable is marked read-only, its value cannot be changed.
For example, the following script generates an error while trying to change the value of NAME −
#!/bin/sh
NAME="Zara Ali"
readonly NAME
NAME="Qadiri"
The above script will generate the following result −
/bin/sh: NAME: This variable is read only.
Unsetting Variables
Page | 2
Unsetting or deleting a variable directs the shell to remove the variable from the list of variables
that it tracks. Once you unset a variable, you cannot access the stored value in the variable.
Following is the syntax to unset a defined variable using the unset command −
unset variable_name
The above command unsets the value of a defined variable. Here is a simple example that
demonstrates how the command works −
#!/bin/sh
NAME="Zara Ali"
unset NAME
echo $NAME
The above example does not print anything. You cannot use the unset command
to unset variables that are marked readonly.
Variable Types
When a shell is running, three main types of variables are present −
Local Variables − A local variable is a variable that is present within the current instance
of the shell. It is not available to programs that are started by the shell. They are set at the
command prompt.
Environment Variables − An environment variable is available to any child process of
the shell. Some programs need environment variables in order to function correctly.
Usually, a shell script defines only those environment variables that are needed by the
programs that it runs.
Shell Variables − A shell variable is a special variable that is set by the shell and is required
by the shell in order to function correctly. Some of these variables are environment
variables whereas others are local variables.
Special Variables
These variables are reserved for specific functions.
For example, the $ character represents the process ID number, or PID, of the current shell −
$echo $$
The above command writes the PID of the current shell −
Page | 3
29949
The following table shows a number of special variables that you can use in your shell scripts −
[Link]. Variable & Description
$0
1
The filename of the current script.
$n
These variables correspond to the arguments with which a script was invoked. Here n is a
2
positive decimal number corresponding to the position of an argument (the first argument is
$1, the second argument is $2, and so on).
$#
3
The number of arguments supplied to a script.
$*
4 All the arguments are double quoted. If a script receives two arguments, $* is equivalent to
$1 $2.
$@
5 All the arguments are individually double quoted. If a script receives two arguments, $@ is
equivalent to $1 $2.
$?
6
The exit status of the last command executed.
$$
7 The process number of the current shell. For shell scripts, this is the process ID under which
they are executing.
$!
8
The process number of the last background command.
Command-Line Arguments
The command-line arguments $1, $2, $3, ...$9 are positional parameters, with $0 pointing to the
actual command, program, shell script, or function and $1, $2, $3, ...$9 as the arguments to the
command.
Following script uses various special variables related to the command line −
#!/bin/sh
echo "File Name: $0"
Page | 4
echo "First Parameter : $1"
echo "Second Parameter : $2"
echo "Quoted Values: $@"
echo "Quoted Values: $*"
echo "Total Number of Parameters : $#"
Here is a sample run for the above script −
$./[Link] Zara Ali
File Name : ./[Link]
First Parameter : Zara
Second Parameter : Ali
Quoted Values: Zara Ali
Quoted Values: Zara Ali
Total Number of Parameters : 2
Special Parameters $* and $@
There are special parameters that allow accessing all the command-line arguments at
once. $* and $@ both will act the same unless they are enclosed in double quotes, "".
Both the parameters specify the command-line arguments. However, the "$*" special parameter
takes the entire list as one argument with spaces between and the "$@" special parameter takes
the entire list and separates it into separate arguments.
We can write the shell script as shown below to process an unknown number of commandline
arguments with either the $* or $@ special parameters −
#!/bin/sh
for TOKEN in $*
do
echo $TOKEN
done
Here is a sample run for the above script −
$./[Link] Zara Ali 10 Years Old
Zara
Ali
10
Years
Page | 5
Old
Note − Here do...done is a kind of loop that will be covered in a subsequent tutorial.
Exit Status
The $? variable represents the exit status of the previous command.
Exit status is a numerical value returned by every command upon its completion. As a rule, most
commands return an exit status of 0 if they were successful, and 1 if they were unsuccessful.
Some commands return additional exit statuses for particular reasons. For example, some
commands differentiate between kinds of errors and will return various exit values depending on
the specific type of failure.
Following is the example of successful command −
$./[Link] Zara Ali
File Name : ./[Link]
First Parameter : Zara
Second Parameter : Ali
Quoted Values: Zara Ali
Quoted Values: Zara Ali
Total Number of Parameters : 2
$echo $?
0
$
Arrays
Shell supports a different type of variable called an array variable. This can hold multiple
values at the same time. Arrays provide a method of grouping a set of variables. Instead of
creating a new name for each variable that is required, you can use a single array variable that
stores all the other variables.
All the naming rules discussed for Shell Variables would be applicable while naming arrays.
Defining Array Values
The difference between an array variable and a scalar variable can be explained as follows.
Page | 6
Suppose you are trying to represent the names of various students as a set of variables. Each of
the individual variables is a scalar variable as follows −
NAME01="Zara"
NAME02="Qadir"
NAME03="Mahnaz"
NAME04="Ayan"
NAME05="Daisy"
We can use a single array to store all the above mentioned names. Following is the simplest
method of creating an array variable. This helps assign a value to one of its indices.
array_name[index]=value
Here array_name is the name of the array, index is the index of the item in the array that you
want to set, and value is the value you want to set for that item.
As an example, the following commands −
NAME[0]="Zara"
NAME[1]="Qadir"
NAME[2]="Mahnaz"
NAME[3]="Ayan"
NAME[4]="Daisy"
If you are using the ksh shell, here is the syntax of array initialization −
set -A array_name value1 value2 ... valuen
If you are using the bash shell, here is the syntax of array initialization −
array_name=(value1 ... valuen)
Accessing Array Values
After you have set any array variable, you access it as follows −
${array_name[index]}
Here array_name is the name of the array, and index is the index of the value to be accessed.
Following is an example to understand the concept −
#!/bin/sh
Page | 7
NAME[0]="Zara"
NAME[1]="Qadir"
NAME[2]="Mahnaz"
NAME[3]="Ayan"
NAME[4]="Daisy"
echo "First Index: ${NAME[0]}"
echo "Second Index: ${NAME[1]}"
The above example will generate the following result −
$./[Link]
First Index: Zara
Second Index: Qadir
You can access all the items in an array in one of the following ways −
${array_name[*]}
${array_name[@]}
Here array_name is the name of the array you are interested in. Following example will help
you understand the concept −
#!/bin/sh
NAME[0]="Zara"
NAME[1]="Qadir"
NAME[2]="Mahnaz"
NAME[3]="Ayan"
NAME[4]="Daisy"
echo "First Method: ${NAME[*]}"
echo "Second Method: ${NAME[@]}"
The above example will generate the following result −
$./[Link]
First Method: Zara Qadir Mahnaz Ayan Daisy
Second Method: Zara Qadir Mahnaz Ayan Daisy
Basic Operators
We will now discuss the following operators −
Page | 8
Arithmetic Operators
Relational Operators
Boolean Operators
String Operators
File Test Operators
Bourne shell didn't originally have any mechanism to perform simple arithmetic operations but it
uses external programs, either awk or expr.
The following example shows how to add two numbers −
Live Demo
#!/bin/sh
val=`expr 2 + 2`
echo "Total value : $val"
The above script will generate the following result −
Total value : 4
The following points need to be considered while adding −
There must be spaces between operators and expressions. For example, 2+2 is not correct;
it should be written as 2 + 2.
The complete expression should be enclosed between ‘ ‘, called the backtick.
Arithmetic Operators
The following arithmetic operators are supported by Bourne Shell.
Assume variable a holds 10 and variable b holds 20 then −
Operator Description Example
`expr $a + $b` will give
+ (Addition) Adds values on either side of the operator
30
Subtracts right hand operand from left hand `expr $a - $b` will give -
- (Subtraction)
operand 10
`expr $a \* $b` will give
* (Multiplication) Multiplies values on either side of the operator
200
Page | 9
Divides left hand operand by right hand
/ (Division) `expr $b / $a` will give 2
operand
Divides left hand operand by right hand `expr $b % $a` will give
% (Modulus)
operand and returns remainder 0
a = $b would assign
= (Assignment) Assigns right operand in left operand
value of b into a
Compares two numbers, if both are same then [ $a == $b ] would return
== (Equality)
returns true. false.
Compares two numbers, if both are different [ $a != $b ] would return
!= (Not Equality)
then returns true. true.
It is very important to understand that all the conditional expressions should be inside square
braces with spaces around them, for example [ $a == $b ] is correct whereas, [$a==$b] is
incorrect.
All the arithmetical calculations are done using long integers.
Relational Operators
Bourne Shell supports the following relational operators that are specific to numeric values.
These operators do not work for string values unless their value is numeric.
For example, following operators will work to check a relation between 10 and 20 as well as in
between "10" and "20" but not in between "ten" and "twenty".
Assume variable a holds 10 and variable b holds 20 then −
Operator Description Example
Checks if the value of two operands are equal or not;
-eq [ $a -eq $b ] is not true.
if yes, then the condition becomes true.
Checks if the value of two operands are equal or not;
-ne if values are not equal, then the condition becomes [ $a -ne $b ] is true.
true.
Checks if the value of left operand is greater than the
-gt value of right operand; if yes, then the condition [ $a -gt $b ] is not true.
becomes true.
Page | 10
Checks if the value of left operand is less than the
-lt value of right operand; if yes, then the condition [ $a -lt $b ] is true.
becomes true.
Checks if the value of left operand is greater than or
-ge equal to the value of right operand; if yes, then the [ $a -ge $b ] is not true.
condition becomes true.
Checks if the value of left operand is less than or
-le equal to the value of right operand; if yes, then the [ $a -le $b ] is true.
condition becomes true.
It is very important to understand that all the conditional expressions should be placed inside
square braces with spaces around them. For example, [ $a <= $b ] is correct whereas, [$a <=
$b] is incorrect.
Boolean Operators
The following Boolean operators are supported by the Bourne Shell.
Assume variable a holds 10 and variable b holds 20 then −
Operator Description Example
This is logical negation. This inverts a true condition
! [ ! false ] is true.
into false and vice versa.
This is logical OR. If one of the operands is true, then
-o [ $a -lt 20 -o $b -gt 100 ] is true.
the condition becomes true.
This is logical AND. If both the operands are true,
-a [ $a -lt 20 -a $b -gt 100 ] is false.
then the condition becomes true otherwise false.
String Operators
The following string operators are supported by Bourne Shell.
Assume variable a holds "abc" and variable b holds "efg" then −
Operator Description Example
Checks if the value of two operands are equal
= [ $a = $b ] is not true.
or not; if yes, then the condition becomes true.
Page | 11
Checks if the value of two operands are equal
!= or not; if values are not equal then the [ $a != $b ] is true.
condition becomes true.
Checks if the given string operand size is zero;
-z [ -z $a ] is not true.
if it is zero length, then it returns true.
Checks if the given string operand size is non-
-n [ -n $a ] is not false.
zero; if it is nonzero length, then it returns true.
Checks if str is not the empty string; if it is
str [ $a ] is not false.
empty, then it returns false.
File Test Operators
We have a few operators that can be used to test various properties associated with a Unix file.
Assume a variable file holds an existing file name "test" the size of which is 100 bytes and
has read, write and execute permission on −
Operator Description Example
Checks if file is a block special file; if yes, then
-b file [ -b $file ] is false.
the condition becomes true.
Checks if file is a character special file; if yes,
-c file [ -c $file ] is false.
then the condition becomes true.
Checks if file is a directory; if yes, then the
-d file [ -d $file ] is not true.
condition becomes true.
Checks if file is an ordinary file as opposed to a
-f file directory or special file; if yes, then the [ -f $file ] is true.
condition becomes true.
Checks if file has its set group ID (SGID) bit
-g file [ -g $file ] is false.
set; if yes, then the condition becomes true.
Checks if file has its sticky bit set; if yes, then
-k file [ -k $file ] is false.
the condition becomes true.
Checks if file is a named pipe; if yes, then the
-p file [ -p $file ] is false.
condition becomes true.
Page | 12
Checks if file descriptor is open and associated
-t file with a terminal; if yes, then the condition [ -t $file ] is false.
becomes true.
Checks if file has its Set User ID (SUID) bit set;
-u file [ -u $file ] is false.
if yes, then the condition becomes true.
Checks if file is readable; if yes, then the
-r file [ -r $file ] is true.
condition becomes true.
Checks if file is writable; if yes, then the
-w file [ -w $file ] is true.
condition becomes true.
Checks if file is executable; if yes, then the
-x file [ -x $file ] is true.
condition becomes true.
Checks if file has size greater than 0; if yes, then
-s file [ -s $file ] is true.
condition becomes true.
Checks if file exists; is true even if file is a
-e file [ -e $file ] is true.
directory but exists.
Decision Making
Unix Shell supports conditional statements which are used to perform different actions based on
different conditions. We will now understand two decision-making statements here −
The if...else statement
The case...esac statement
The if...else statements
If else statements are useful decision-making statements which can be used to select an option
from a given set of options.
Unix Shell supports following forms of if…else statement −
if...fi statement
if...else...fi statement
if...elif...else...fi statement
Most of the if statements check relations using relational operators discussed in the previous
chapter.
Page | 13
The case...esac Statement
You can use multiple if...elif statements to perform a multiway branch. However, this is not
always the best solution, especially when all of the branches depend on the value of a single
variable.
Unix Shell supports case...esac statement which handles exactly this situation, and it does so
more efficiently than repeated if...elif statements.
The case...esac statement in the Unix shell is very similar to the switch...case statement we have
in other programming languages like C or C++ and PERL, etc.
Loops
1. While Loop
The while loop syntax in the shell scripting will be represented in the following way.
Syntax:
while [ condition ]
do
command1
command2
done
Example:
While loop to display numbers from 1 to 10.
Code:
number = 1
while [ $number –lt 11 ]
do
echo $number
((number++))
Done
Code Explanation: In the above example, we are trying to display numbers from 1 to 10. The
statement number =1 is initializing the conditional variable and $number –lt 11 is the conditional
checking statement where it is checking whether the number is less than 11 where –lt is less than.
If this condition satisfies then the body of the loop will execute where we are displaying number
Page | 14
and incrementing the number so that during the next iteration it will display the next number and
process repeats until it satisfies the condition.
2. For Loop
For loop is another type of looping statement to execute a set of commands for a certain number
of times. Let’s have a look at the syntax of for loop in shell scripting and it can be represented as
below:
Syntax:
for var in list
do
command 1
command 2
done
Example:
For loop, example to display names from a list.
Code:
for p_name in Stan Kyle Cartman
do
echo $p_name
done
Code Explanation: In the above example, we are trying to iterative over the list of names and
execute the commands inside the body of the loop until all the elements or values in the list are
processed. In the above example, p_name is variable which will have the names for every
iteration one by one and it will execute the echo command in the body of the for loop and the
same process repeats until all the variables in the list are completed then it will come out of the
loop.
Page | 15
3. Until Loop
Until loop is one of the looping statements in the shell scripting and this looping statement is
similar to the while loop statement which we have discussed earlier. The difference between two
is, it will execute the body of the loop until the conditional statement becomes true
whereas while loop executes commands if the condition is true. Let us have a look at the syntax
of until loop in the shell scripting as below:
Syntax:
until [ conditional statement ]
do
command1
command2
done
Example:
Until example to display numbers from 1 to 10.
Code:
number = 1
until [ $number –gt 10 ]
do
echo $number
((number++))
done
Code Explanation: In the above example, the number is a variable which we used to validate
the condition and -gt is greater than some number. Until the loop will execute the body of the
loop until the condition becomes true. In the above example, the body of the loop will display the
numbers until the number is greater than 10 and the number is incremented for every iteration
Page | 16
until the loop continues to execute. Once the condition evaluates to true then until loop will
terminate. If we use the same condition in a while loop it will execute the body of the loop after.
Loop Control Statements
In this chapter, we will learn following two statements that are used to control shell loops−
The break statement
The continue statement
The infinite Loop
All the loops have a limited life and they come out once the condition is false or true depending
on the loop.
A loop may continue forever if the required condition is not met. A loop that executes forever
without terminating executes for an infinite number of times. For this reason, such loops are
called infinite loops.
Example
Here is a simple example that uses the while loop to display the numbers zero to nine −
#!/bin/sh
a=10
until [ $a -lt 10 ]
do
echo $a
a=`expr $a + 1`
done
This loop continues forever because a is always greater than or equal to 10 and it is never less
than 10.
The break Statement
The break statement is used to terminate the execution of the entire loop, after completing the
execution of all of the lines of code up to the break statement. It then steps down to the code
following the end of the loop.
Page | 17
Syntax
The following break statement is used to come out of a loop −
break
The break command can also be used to exit from a nested loop using this format −
break n
Here n specifies the nth enclosing loop to the exit from.
Example
Here is a simple example which shows that loop terminates as soon as a becomes 5 −
#!/bin/sh
a=0
while [ $a -lt 10 ]
do
echo $a
if [ $a -eq 5 ]
then
break
fi
a=`expr $a + 1`
done
Upon execution, you will receive the following result −
0
1
2
3
4
5
Here is a simple example of nested for loop. This script breaks out of both loops if var1 equals
2 and var2 equals 0 −
#!/bin/sh
Page | 18
for var1 in 1 2 3
do
for var2 in 0 5
do
if [ $var1 -eq 2 -a $var2 -eq 0 ]
then
break 2
else
echo "$var1 $var2"
fi
done
done
Upon execution, you will receive the following result. In the inner loop, you have a break
command with the argument 2. This indicates that if a condition is met you should break out of
outer loop and ultimately from the inner loop as well.
10
15
The continue statement
The continue statement is similar to the break command, except that it causes the current
iteration of the loop to exit, rather than the entire loop.
This statement is useful when an error has occurred but you want to try to execute the next
iteration of the loop.
Syntax
continue
Like with the break statement, an integer argument can be given to the continue command to
skip commands from nested loops.
continue n
Here n specifies the nth enclosing loop to continue from.
Example
The following loop makes use of the continue statement which returns from the continue
statement and starts processing the next statement −
Page | 19
#!/bin/sh
NUMS="1 2 3 4 5 6 7"
for NUM in $NUMS
do
Q=`expr $NUM % 2`
if [ $Q -eq 0 ]
then
echo "Number is an even number!!"
continue
fi
echo "Found odd number"
done
Upon execution, you will receive the following result −
Found odd number
Number is an even number!!
Found odd number
Number is an even number!!
Found odd number
Number is an even number!!
Found odd number
References
[1] [Link]
Page | 20