Shell Script
1.1 Shell Scripts:
The basic concept of a shell script is a list of commands, which are listed in the
order of execution. A good shell script will have comments, preceded by a pound
sign, #, describing the steps.
There are conditional tests, such as value A is greater than value B, loops allowing
us to go through massive amounts of data, files to read and store data, and
variables to read and store data, and the script may include functions.
Shell scripts and functions are both interpreted. This means they are not compiled.
Example Script:
Assume we create a test.sh script. Note all the scripts would have .sh extension.
Before you add anything else to your script, you need to alert the system that a
shell script is being started.
# vi test.sh
Write these commands in this file.
pwd
ls
You can put your comments( #) in your script as follows:
# Author : Zara Ali
# Copyright (c) Tutorialspoint.com
# Script follows here:
pwd
ls
Now you save the above content (Escape and : wq) and make this script
executable as follows:
$chmod 755 test.sh
Now you have your shell script ready to be executed as follows:
$./test.sh
This would produce following result:
/home/amrood
index.htm unix-basic_utilities.htm unix-directories.htm
test.sh unix-communication.htm unix-environment.htm
Note: To execute your any program available in current directory you would
execute using ./program_name
1.2 Variable in shell script:
A variable is a character string to which we assign a value. The value assigned
could be a number, text, filename, device, or any other type of data.
In Linux (Shell), there are two types of variable:
(1) System variables - Created and maintained by Linux itself. This type of ariable
defined in CAPITAL LETTERS.
(2) User defined variables (UDV) - Created and maintained by user. This type of
variable defined in lower letters.
You can see system variables by giving command like $ set, some of the important
System variables are:
SystemVariable
Meaning
BASH=/bin/bash
Ourshellname
BASH_VERSION=1.14.7(1)
Ourshellversionname
COLUMNS=80
No.ofcolumnsforourscreen
HOME=/home/vivek
Ourhomedirectory
LINES=25
No.ofcolumnsforourscreen
LOGNAME=students
studentsOurloggingname
OSTYPE=Linux
OurOstype
PATH=/usr/bin:/sbin:/bin:/usr/sbin Ourpathsettings
PS1=[\u@\h\W]\$
Ourpromptsettings
PWD=/home/students/Common
Ourcurrentworkingdirectory
SHELL=/bin/bash
Ourshellname
USERNAME=vivek
UsernamewhoiscurrentlylogintothisPC
You can print any of the above variables content as follows:
$ echo $USERNAME
$ echo $HOME
Exercise:
1) If you want to print your home directory location then you give command:
a)$ echo $HOME
OR
(b)$ echo HOME
Which of the above command is correct & why?
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 would 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"
Above example defines the variable NAME and assigns it the value "Zara Ali".
Variables of this type are called scalar variables. A scalar variable can hold only
one value at a time.
The 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, following script would access the value of defined variable NAME
and would print it on STDOUT:
vi test.sh
NAME="Zara Ali"
echo $NAME
./test.sh
This would produce following value:
Zara Ali
1.3 Operators in shell :
There are various operators supported by each shell. Our tutorial is based on
default shell (Bourne) so we are going to cover all the important Bourne Shell
operators in the tutorial.
There are following operators which we are going to discuss:
Arithmetic Operators.
Relational Operators.
Boolean Operators.
String Operators.
File Test Operators.
The Bourne shell didn't originally have any mechanism to perform simple
arithmetic but it uses external programs, either awk or the must simpler program
expr.
Here is simple example to add two numbers:
Vi test.sh
val=`expr 2 + 2`
echo "Total value : $val"
This would produce following result:
Total value : 4
There are following points to note down:
There must be spaces between operators and expressions for example 2+2 is
not correct, where as it should be written as 2 + 2.
Complete expression should be enclosed between ``, called inverted
commas.
Arithmetic Operators:
There are following arithmetic operators supported by Bourne Shell.
Assume variable a holds 10 and variable b holds 20 then:
Operator Description
Example
Addition - Adds values on either side
of the operator
`expr $a + $b` will give 30
Subtraction - Subtracts right hand
operand from left hand operand
`expr $a - $b` will give -10
Multiplication - Multiplies values on
either side of the operator
`expr $a \* $b` will give 200
Division - Divides left hand operand
`expr $b / $a` will give 2
by right hand operand
Modulus - Divides left hand operand
by right hand operand and returns
remainder
`expr $b % $a` will give 0
Assignment - Assign right operand in
left operand
a=$b would assign value of b
into a
==
Equality - Compares two numbers, if
both are same then returns true.
[ $a == $b ] would return
false.
!=
Not Equality - Compares two numbers,
[ $a != $b ] would return true.
if both are different then returns true.
It is very important to note here that all the conditional expressions would be put
inside square braces with one spaces around them, for example [ $a == $b ] is
correct where as [$a==$b] is incorrect.
All the arithmetical calculations are done using long integers.
Relational Operators:
Bourne Shell supports following relational operators which are specific to numeric
values. These operators would not work for string values unless their value is
numeric.
For example, following operators would 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
-eq
Checks if the value of two operands
are equal or not, if yes then condition
becomes true.
-ne
Checks if the value of two operands
are equal or not, if values are not equal [ $a -ne $b ] is true.
then condition becomes true.
-gt
Checks if the value of left operand is
greater than the value of right operand, [ $a -gt $b ] is not true.
if yes then condition becomes true.
-lt
Checks if the value of left operand is
less than the value of right operand, if
yes then condition becomes true.
[ $a -lt $b ] is true.
-ge
Checks if the value of left operand is
greater than or equal to the value of
right operand, if yes then condition
becomes true.
[ $a -ge $b ] is not true.
-le
Checks if the value of left operand is
less than or equal to the value of right
[ $a -le $b ] is true.
operand, if yes then condition becomes
true.
[ $a -eq $b ] is not true.
It is very important to note here that all the conditional expressions would be put
inside square braces with one spaces around them, for example [ $a <= $b ] is
correct where as [$a <= $b] is incorrect.
Boolean Operators:
There are following boolean operators supported by Bourne Shell.
Assume variable a holds 10 and variable b holds 20 then:
Operator Description
Example
This is logical negation. This inverts a
[ ! false ] is true.
true condition into false and vice versa.
-o
This is logical OR. If one of the
operands is true then condition would
be true.
-a
This is logical AND. If both the
[ $a -lt 20 -a $b -gt 100 ] is
operands are true then condition would
false.
be true otherwise it would be false.
[ $a -lt 20 -o $b -gt 100 ] is
true.
String Operators:
if yes then
condition becomes
true.
[ $a = $b ] is not true.
!=
Checks if the value of two operands are equal or
[ $a != $b ]
not, if values are not equal then condition
is true.
becomes true.
-z
Checks if the given string operand size is zero. If [ -z $a ] is
it is zero length then it returns true.
not true.
-n
Checks if the given string operand size is nonzero. If it is non-zero length then it returns true.
[ -z $a ] is
not false.
str
Check if str is not the empty string. If it is empty [ $a ] is not
then it returns false.
false.
File Test Operators:
There are following operators to test various properties associated with a Unix file.
Assume a variable file holds an existing file name "test" whose size is 100 bytes
and has read, write and execute permission on:
Operator Description
Example
-b file
Checks if file is a block special file if
yes then condition becomes true.
-c file
Checks if file is a character special file
[ -b $file ] is false.
if yes then condition becomes true.
-d file
Check if file is a directory if yes then
condition becomes true.
-f file
Check if file is an ordinary file as
opposed to a directory or special file if [ -f $file ] is true.
yes then condition becomes true.
-r file
Checks if file is readable if yes then
condition becomes true.
[ -r $file ] is true.
-w file
Check if file is writable if yes then
condition becomes true.
[ -w $file ] is true.
-x file
Check if file is execute if yes then
[ -x $file ] is true.
[ -b $file ] is false.
[ -d $file ] is not true.
condition becomes true.
-s file
Check if file has size greater than 0 if
yes then condition becomes true.
[ -s $file ] is true.
-e file
Check if file exists. Is true even if file
is a directory but exists.
[ -e $file ] is true.
test statement is used to evaluate condition on its right and returns either true or
false exit status( see section 1.5), which then used by if ( see in next
assignments/notes) for making decisions is used statement. test is used in three
ways :
Example:
1.4 About Quotes
There are three types of quotes
Quotes
"
Name
Double
Quotes
Meaning
"Double Quotes" - Anything enclose in double quotes
removed meaning of that characters (except \ and $).
'
Single
quotes
Back quote
'Single quotes' - Enclosed in single quotes remains unchanged.
`Back quote` - To execute command
Example:
$ echo "Today is date"
Can't print message with today's date.
$ echo "Today is `date`".
It will print today's date as, Today is Tue Jan ....,Can you see that the `date`
statement uses back quote?
1.5 Exit Status
By default in Linux if particular command/shell script is executed, it return two
type of values which is used to see whether command or shell script executed is
successful or not.
(1) If return value is zero (0), command is successful.
(2) If return value is nonzero, command is not successful or some sort of error
executing command/shell script.
This value is know as Exit Status.
But how to find out exit status of command or shell script?
Simple, to determine this exit Status you can use $? special variable of shell.
For e.g. (This example assumes that unknow1file doest not exist on your hard
drive)
$ rm unknow1file
It will show error as follows
rm: cannot remove `unkowm1file': No such file or directory
and after that if you give command
$ echo $?
it will print nonzero value to indicate error. Now give command
$ ls
$ echo $?
It will print 0 to indicate command is successful.
1.6 The read Statement
Use to get input (data from user) from keyboard and store (data) to variable.
Syntax:
read variable1, variable2,...variableN
Following script first ask user, name and then waits to enter name from the user via
keyboard. Then user enters name from keyboard (after giving name you have to
press ENTER key) and entered name through keyboard is stored (assigned) to
variable fname.
$ vi sayH
#
#Script to read your name from key-board
#
echo "Your first name please:"
read fname
echo "Hello $fname, Lets be friend!"
Run it as follows:
$ chmod 755 sayH
$ ./sayH
1.7 Wild cards (Filename Shorthand or meta Characters)
Wild card
/Shorthand
Meaning
Matches any string or group
of characters.
Examples
$ ls *
will show all files
$ ls a*
will show all files
whose first name is
starting with letter
'a'
$ ls *.c
will show all files
having extension .c
$ ls ut*.c
will show all files
having extension .c
but file name must
begin with 'ut'.
$ ls ?
will show all files
whose names are 1
character long
$ ls fo?
will show all files
whose names are 3
character long and
file name begin
with fo
$ ls [abc]*
will show all files
beginning with
letters a,b,c
Matches any single
character.
[...]
Matches any one of the
enclosed characters
Note:
[..-..] A pair of characters separated by a minus sign denotes a range.
Example:
$ ls /bin/[a-c]*
Will show all files name beginning with letter a,b or c like
/bin/arch
/bin/awk
/bin/bsh /bin/chmod
/bin/cp
/bin/ash
/bin/basename /bin/cat /bin/chown
/bin/cpio
/bin/ash.static /bin/bash
/bin/chgrp /bin/consolechars /bin/csh
But
$ ls /bin/[!a-o]
$ ls /bin/[^a-o]
If the first character following the [ is a ! or a ^ ,then any character not enclosed is
matched i.e. do not show us file name that beginning with a,b,c,e...o, like
/bin/ps
/bin/rvi
/bin/sleep /bin/touch /bin/view
/bin/pwd
/bin/rview
/bin/sort /bin/true
/bin/wcomp
/bin/red
/bin/sayHello /bin/stty /bin/umount /bin/xconf
/bin/remadmin /bin/sed
/bin/su /bin/uname /bin/ypdomainname
/bin/rm
/bin/setserial /bin/sync /bin/userconf /bin/zcat
/bin/rmdir
/bin/sfxload /bin/tar /bin/usleep
/bin/rpm
/bin/sh
/bin/tcsh /bin/vi
1.8 Pipe
You can connect two commands together so that the output from one program
becomes the input of the next program. Two or more commands connected in this
way form a pipe.
To make a pipe, put a vertical bar (|) on the command line between two commands.
When a program takes its input from another program, performs some operation on
that input, and writes the result to the standard output, it is referred to as a filter.
Syntax:
command1 | command2
Examles:
Command using Pipes
$ ls | more
$ who | sort
Meaning or Use of Pipes
Output of ls command is given as input
to more command So that output is
printed one screen full page at a time.
Output of who command is given as
input to sort command So that it will
print sorted list of users
$ who | sort > user_list
$ who | wc -l
$ ls -l | wc -l
$ who | grep raju
Same as above except output of sort is
send to (redirected) user_list file
Output of who command is given as
input to wc command So that it will
number of user who logon to system
Output of ls command is given as input
to wc command So that it will print
number of files in current directory.
Output of who command is given as
input to grep command So that it will
print if particular user name if he is
logon or nothing is printed (To see
particular user is logon or not)
1.9 Redirection of Standard output/input i.e. Input - Output
redirection
Mostly all command gives output on screen or take input from keyboard, but in
Linux (and in other OSs also) it's possible to send output to file or to read input
from file.
For e.g.
$ ls command gives output to screen; to send output to file of ls command give
command
$ ls > filename
It means put output of ls command to filename.
There are three main redirection symbols >,>>,<
(1) > Redirector Symbol
Syntax:
Linux-command > filename
To output Linux-commands result (output of command or shell script) to file. Note
that if file already exist, it will be overwritten else new file is created. For e.g. To
send output of ls command give
$ ls > myfiles
Now if 'myfiles' file exist in your current directory it will be overwritten without
any type of warning.
(2) >> Redirector Symbol
Syntax:
Linux-command >> filename
To output Linux-commands result (output of command or shell script) to END of
file. Note that if file exist , it will be opened and new information/data will be
written to END of file, without losing previous information/data, And if file is not
exist, then new file is created. For e.g. To send output of date command to already
exist file give command
$ date >> myfiles
(3) < Redirector Symbol
Syntax:
Linux-command < filename
To take input to Linux-command from file instead of key-board. For e.g. To take
input for cat command give
$ cat < myfiles
You can also use above redirectors simultaneously as follows
Create text file sname as follows
$cat > sname
vivek
ashish
zebra
babu
Press CTRL + D to save.
Now issue following command.
$ sort < sname > sorted_names
$ cat sorted_names
ashish
babu
vivek
zebra
In above example sort ($ sort < sname > sorted_names) command takes input
from sname file and output of sort command (i.e. sorted names) is redirected to
sorted_names file.
Try one more example to clear your idea:
$ tr "[a-z]" "[A-Z]" < sname > cap_names
$ cat cap_names
VIVEK
ASHISH
ZEBRA
BABU
tr command is used to translate all lower case characters to upper-case letters. It
take input from sname file, and tr's output is redirected to cap_names file.
Future Point : Try following command and find out most important point:
$ sort > new_sorted_names < sname
$ cat new_sorted_names
1.10 Command line arguments:
Why is it necessary to write something about command line arguments? The
concept is very easy and clear: if you enter the following command
$ ls -l *.txt
the command "ls" is executed with the command line flag "-l" and all files in the
current directory ending with ".txt" as arguments
Similarly, to input arguments into a shell script, like any normal command line
program, shell sets some environment variables according to the command line
arguments specified:
$0
The name the script was invoked with. This may be a basename without
directory component, or a path name. This variable is not changed with
subsequent shift commands.
$1, The first, second, third, ... command line argument, respectively. The
$2, argument may contain whitespace if the argument was quoted, i.e. "two
$3, ... words".
$#
Number of command line arguments, not counting the invocation name
$0
$@
"$@" is replaced with all command line arguments, enclosed in quotes,
i.e. "one", "two three", "four". Whitespace within an argument is
preserved.
$*
$* is replaced with all command line arguments. Whitespace is not
preserved, i.e. "one", "two three", "four" would be changed to "one",
"two", "three", "four".
This variable is not used very often, "$@" is the normal case, because it
leaves the arguments unchanged.
Example
o
o
command: ./example.sh alpha beta gamma
Variables: $1=='alpha'; $2=='beta'; $3=='gamma'
The variable $0 is the script's name. The total number of arguments is stored in $#.
The variables $* return all the arguments.
Example
vi script.sh
echo "the $1 eats a $2 every time there is a $3"
echo "bye:-)"
$ ./script.sh dog bone moose
Output:
the dog eats a bone every time there is a moose
bye:-)