Linux Shell Scripting Tutorial
Linux Shell Scripting Tutorial
INDEX
● Introduction
❍ Kernel
❍ Shell
❍ How to use Shell
❍ Common Linux Command Introduction
● Process
❍ Why Process required
❍ Linux commands related with process
● Redirection of Standard output/input
❍ Redirectors
❍ Pipes
❍ Filters
● Shell Programming
❍ Variables in Linux
❍ How to define User defined variables
❍ Rules for Naming variable name
❍ How to print or access value of UDV (User defined variables)
❍ How to write shell script
❍ How to Run Shell Scripts
❍ Quotes in Shell Scripts
❍ Shell Arithmetic
❍ Command Line Processing (Command Line Arguments)
❍ Why Command Line arguments required
❍ Exit Status
❍ Filename Shorthand or meta Characters (i.e. wild cards)
● Programming Commands
❍ echo command
❍ Decision making in shell script ( i.e. if command)
❍ test command or [ expr ]
❍ Loop in shell scripts
❍ The case Statement
❍ The read Statement
● More Advanced Shell Script Commands
❍ /dev/null - Use to send unwanted output of program
❍ Local and Global Shell variable (export command)
❍ Conditional execution i.e. && and ||
❍ I/O Redirection and file descriptors
❍ Functions
❍ User Interface and dialog utility
❍ trap command
❍ getopts command
❍ More examples of Shell Script (Exercise for You :-)
© 1998-2000 FreeOS.com (I) Pvt. Ltd. All rights reserved.
Introduction
This tutorial is designed for beginners only and This tutorial explains the basics of
shell programming by showing some examples of shell programs. Its not help or
manual for the shell. While reading this tutorial you can find manual quite useful (
type man bash at $ prompt to see manual pages). Manual contains all necessary
information you need, but it won't have that much examples, which makes idea
more clear. For that reason, this tutorial contains examples rather than all the
features of shell. I assumes you have at least working knowledge of Linux i.e. basic
commands like how to create, copy, remove files/directories etc or how to use
editor like vi or mcedit and login to your system. Before Starting Linux Shell Script
Programming you must know
● Kernel
● Shell
● Process
What's Kernel
Kernel is hart of Linux O/S. It manages resource of Linux O/S. Resources means
facilities available in Linux. For eg. Facility to store data, print data on printer,
memory, file management etc . Kernel decides who will use this resource, for how
long and when. It runs your programs (or set up to execute binary files) It's
Memory resident portion of Linux. It performance following task :-
● I/O management
● Process management
● Device management
● File management
● Memory management
Any of the above shell reads command from user (via Keyboard or Mouse) and tells
Linux O/s what users want. If we are giving commands from keyboard it is called
command line interface ( Usually in-front of $ prompt, This prompt is depend upon
your shell and Environment that you set or by your System Administrator,
therefore you may get different prompt ).
NOTE: To find your shell type following command
$ echo $SHELL
$ ls --help | more
Syntax: command-name --help
Syntax: man command-name
Syntax: info command-name
See what happened when you type following
$ man ls
$ info bash
NOTE: In MS-DOS, you get help by using /? clue or by typing help command as
C:\> dir /?
C:\> date /?
C:\> help time
C:\> help date
C:\> help
Linux Command
Example ( In front of $
For this Purpose Use this Command Syntax
Prompt)
To see date date $ date
To see who's using
who $ who
system.
Print working directory pwd $ pwd
List name of files in
ls or dirs $ ls
current directory
To create text file $ cat > myfile
NOTE: Press and hold type your text
CTRL key and press D to cat > { file name } when done press
stop or to end file ^D
(CTRL+D)
To text see files cat {file name } $ cat myfile
To display file one full
more {file name } $ more myfile
screen at a time
To move or rename $ mv sales
mv {file1} {file2}
file/directory sales.99
To create multiple file
copies with various link.
After this both oldfile ln {oldfile} {newfile} $ ln Page1 Book1
newfile refers to same
name
To remove file rm file1 $ rm myfile
What is Processes
Process is any kind of program or task carried out by your PC. For e.g. $ ls -lR , is
command or a request to list files in a directory and all subdirectory in your current
directory. It is a process. A process is program (command given by user) to
perform some Job. In Linux when you start process, it gives a number (called PID
or process-id), PID starts from 0 to 65535.
Pips
A pipe is a way to connect the output of one program to the input of another
program without any temporary file.
A pipe is nothing but a temporary storage place where the output of one command
is stored and then passed as the input for second command. Pipes are used to run
more than two commands ( Multiple commands) from same command line.
Syntax: command1 | command2
Command using Pips Meaning or Use of Pipes
Here the output of ls command is given as input to
$ ls | more more command So that output is printed one screen
full page at a time
Here output of who command is given as input to
$ who | sort sort command So that it will print sorted list of
users
Here output of who command is given as input to
$ who | wc -l wc command So that it will number of user who
logon to system
Here output of ls command is given as input to wc
$ ls -l | wc -l command So that it will print number of files in
current directory.
Here output of who command is given as input to
grep command So that it will print if particular user
$ who | grep raju
name if he is logon or nothing is printed ( To see
for particular user logon)
Filter
If a Linux command accepts its input from the standard input and produces its
output on standard output is know as a filter. A filter performs some kind of
process on the input and gives output. For e.g.. Suppose we have file called
'hotel.txt' with 100 lines data, And from 'hotel.txt' we would like to print contains
from line number 20 to line number 30 and store this result to file called 'hlist' then
give command
$ tail +20 < hotel.txt | head -n30 >hlist
Here head is filter which takes its input from tail command (tail command start
selecting from line number 20 of given file i.e. hotel.txt) and passes this lines to
input to head, whose output is redirected to 'hlist' file.
© 1998-2000 FreeOS.com (I) Pvt. Ltd. All rights reserved.
Variables in Linux
Sometimes to process our data/information, it must be kept in computers RAM memory. RAM
memory is divided into small locations, and each location had unique number called memory
location/address, which is used to hold our data. Programmer can give a unique name to this
memory location/address called memory variable or variable (Its a named storage location that may
take different values, but only one at a time). In Linux, there are two types of variable
1) System variables - Created and maintained by Linux itself. This type of variable defined in
CAPITAL LETTERS.
2) User defined variables (UDV) - Created and maintained by user. This type of variable defined
in lower LETTERS.
NOTE that Some of the above settings can be different in your PC. You can print any of the above
variables contain as follows
$ echo $USERNAME
$ echo $HOME
Caution: Do not modify System variable this can some time create problems.
$ vech=Bus
To define variable called n having value 10
$ n=10
Rules for Naming variable name (Both UDV and System Variable)
(1) Variable name must begin with Alphanumeric character or underscore character (_), followed by
one or more Alphanumeric character. For e.g. Valid shell variable are as follows
HOME
SYSTEM_VERSION
vech
no
(2) Don't put spaces on either side of the equal sign when assigning value to variable. For e.g.. In
following variable declaration there will be no error
$ no=10
But here there will be problem for following
$ no =10
$ no= 10
$ no = 10
(3) Variables are case-sensitive, just like filename in Linux. For e.g.
$ no=10
$ No=11
$ NO=20
$ nO=2
Above all are different variable name, so to print value 20 we have to use $ echo $NO and Not any
of the following
$ echo $no # will print 10 but not 20
$ echo $No # will print 11 but not 20
$ echo $nO # will print 2 but not 20
(4) You can define NULL variable as follows (NULL variable is variable which has no value at the time
of definition) For e.g.
$ vech=
$ vech=""
Try to print it's value $ echo $vech , Here nothing will be shown because variable has no value i.e.
NULL variable.
Q.4.How to define two variable x=20, y=5 and then to print division of x and y (i.e. x/y)
$x=20
$ y=5
$ expr x / y
Press Ctrl + D to save. Now our script is ready. To execute it type command
$ ./first
This will give error since we have not set Execute permission for our script first; to do this type
command
$ chmod +x first
$ ./first
First screen will be clear, then Knowledge is Power is printed on screen. To print message of
variables contains we user echo command, general form of echo command is as follows
echo "Message"
echo "Message variable1, variable2....variableN"
Now every time you have to give all this detailed as you work in other directory, this take time and
you have to remember complete path. There is another way, if you notice that all of our programs
(in form of executable files) are marked as executable and can be directly executed from prompt
from any directory (To see executables of our normal program give command $ ls -l /bin or ls -l
/usr/bin) by typing command like
$ bc
$ cc myprg.c
$ cal
etc, How this happed? All our executables files are installed in directory called /bin and /bin directory
is set in your PATH setting, Now when you type name of any command at $ prompt, what shell do is
it first look that command in its internal part (called as internal command, which is part of Shell
itself, and always available to execute, since they do not need extra executable file), if found as
internal command shell will execute it, If not found It will look for current directory, if found shell
will execute command from current directory, if not found, then Shell will Look PATH setting, and try
to find our requested commands executable file in all of the directories mentioned in PATH settings,
if found it will execute it, otherwise it will give message "bash: xxxx :command not found", Still
there is one question remain can I run my shell script same as these executables. Yes you can, for
this purpose create bin directory in your home directory and then copy your tested version of shell
script to this bin directory. After this you can run you script as executable file without using $ ./shell
script-name syntax, Following are steps
$ cd
$ mkdir bin
$ cp first ~/bin
$ first
Each of above command Explanation
Each of above command Explanation
$ cd Go to your home directory
Now created bin directory, to install your own shell
$ mkdir bin script, so that script can be run as independent
program or can be accessed from any directory
$ cp first ~/bin copy your script 'first' to your bin directory
$ first Test whether script is running or not (It will run)
In shell script comment is given with # character. This comments are ignored by your shell.
Comments are used to indicate use of script or person who creates/maintained script, or for some
programming explanation etc. Remember always set Execute permission for you script.
NOTE: $# holds number of arguments specified on command line. and $* or $@ refer to all
arguments in passed to script. Now to obtain total no. of Argument to particular script, your $#
variable.
Let's take rm command, which is used to remove file, But which file you want to remove and how
you will you tail this to rm command (Even rm command does not ask you name of file that would
like to remove). So what we do is we write as command as follows
$ rm {file-name}
Here rm is command and file-name is file which you would like to remove. This way you tail to rm
command which file you would like to remove. So we are doing one way communication with our
command by specifying file-name. Also you can pass command line arguments to your script to
make it more users friendly. But how we address or access command line argument in our script.
Lets take ls command
$ ls -a /*
This command has 2 command line argument -a and /* is another. For shell script,
$ myshell foo bar
In shell if we wish to refer this command line argument we refer above as follows
myshell it is $0
foo it is $1
bar it is $2
Here $# will be 2 (Since foo and bar only two Arguments), Please note At a time such 9 arguments
can be used from $0..$9, You can also refer all of them by using $* (which expand to
`$0,$1,$2...$9`) Now try to write following for commands, Shell Script Name ($0), No. of
Arguments (i.e. $#), And actual argument (i.e. $1,$2 etc)
$ sum 11 20
$ math 4 - 7
$d
$ bp -5 myf +20
$ ls *
$ cal
$ findBS 4 8 24 BIG
Shell Script Name No. Of Arguments to script Actual Argument ($1,..$9)
$0 $# $0 $1 $2 $3 $4
sum 2 11 20
math 3 4 - 7
d 0
bp 3 -5 myf +20
ls 1 *
cal 0
findBS 4 4 8 24 BIG
For e.g. now will write script to print command ling argument and we will see how to access them
$ cat > demo
#!/bin/sh
#
# Script that demos, command line args
#
echo "Total number of command line argument are $#"
echo "$0 is script name"
echo "$1 is first argument"
echo $2 is second argument"
echo "All of them are :- $*"
(5)Exit Status
By default in Linux if particular command is executed, it return two type of values, (Values are used
to see whether command is successful or not) if return value is zero (0), command is successful, if
return value is nonzero (>0), command is not successful or some sort of error executing
command/shell script. This value is know as Exit Status of that command. To determine this exit
Status we use $? variable of shell. For eg.
$ 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(>0) to indicate error. Now give command
$ ls
$ echo $?
It will print 0 to indicate command is successful. Try the following commands and not down there
exit status
$ expr 1 + 3
$ echo $?
$ echo Welcome
$ echo $?
$ wildwest canwork?
$ echo $?
$ date
$ echo $?
$ echon $?
$ echo $?
(6)if-then-fi for decision making is shell script Before making any decision in Shell script you must
know following things Type bc at $ prompt to start Linux calculator program
$ bc
After this command bc is started and waiting for you commands, i.e. give it some calculation as
follows type 5 + 2 as
5+2
7
7 is response of bc i.e. addition of 5 + 2 you can even try
5-2
5/2
Now what happened if you type 5 > 2 as follows
5>2
0
0 (Zero) is response of bc, How? Here it compare 5 with 2 as, Is 5 is greater then 2, (If I ask same
question to you, your answer will be YES) In Linux (bc) gives this 'YES' answer by showing 0 (Zero)
value. It means when ever there is any type of comparison in Linux Shell It gives only two answer
one is YES and NO is other.
Linux Shell
Meaning Example
Value
Zero Value (0) Yes/True 0
-1, 32, 55
NON-ZERO
No/False anything but not
Value (> 0)
zero
Try following in bc to clear your Idea and not down bc's response
5 > 12
5 == 10
5 != 2
5 == 5
12 < 2
BC's Response (i.e. Linux Shell
Expression Meaning to us Your Answer representation in zero & non-zero
value)
5 > 12 Is 5 greater than 12 NO 0
5 == 10 Is 5 is equal to 10 NO 0
5 != 2 Is 5 is NOT equal to 2 YES 1
5 == 5 Is 5 is equal to 5 YES 1
1<2 Is 1 is less than 2 Yes 1
Now will see, if condition which is used for decision making in shell script, If given condition is true
then command1 is executed.
Syntax:
if condition
then
command1 if condition is true or if exit status
of condition is 0 (zero)
...
...
fi
Here condition is nothing but comparison between two values, for compression we can use test or [
expr ] statements or even exist status can be also used. An expression is nothing but combination of
values, relational operator (such as >,<, <> etc) and mathematical operators (such as +, -, / etc ).
Following are all examples of expression:
5>2
3+6
3 * 65
a<b
c>5
c > 5 + 30 -1
Type following command (assumes you have file called foo)
$ cat foo
$ echo $?
The cat command return zero(0) on successful, this can be used in if condition as follows, Write shell
script as
$ cat > showfile
#!/bin/sh
#
#Script to print file
#
if cat $1
then
echo -e "\n\nFile $1, found and successfully echoed"
fi
B) If bar file not present on your disk and you give command, $ ./trmfi bar what will be output.
C) And if you type $ ./trmfi, What will be output.
Run it as follows
$ chmod +x ispostive
$ ispostive 5
Here o/p : 5 number is positive
$ispostive -45
Here o/p : Nothing is printed
$ispostive
Here o/p : ./ispostive: test: -gt: unary operator expected
The line, if test $1 -gt 0 , test to see if first command line argument($1) is greater than 0. If it is
true(0) then test will return 0 and output will printed as 5 number is positive but for -45 argument
there is no output because our condition is not true(0) (no -45 is not greater than 0) hence echo
statement is skipped. And for last statement we have not supplied any argument hence error
./ispostive: test: -gt: unary operator expected is generated by shell , to avoid such error we can test
whether command line argument is supplied or not. (See command 8 Script example). test or [ expr
] works with
1.Integer ( Number without decimal point)
2.File types
3.Character strings
For Mathematics use following operator in Shell Script
Math- ematical
Normal Arithmetical/
Operator in Meaning But in Shell
Mathematical Statements
Shell Script
For [ expr ]
For test statement
statement with if
with if command
command
-eq is equal to 5 == 6 if test 5 -eq 6 if expr [ 5 -eq 6 ]
-ne is not equal to 5 != 6 if test 5 -ne 6 if expr [ 5 -ne 6 ]
-lt is less than 5<6 if test 5 -lt 6 if expr [ 5 -lt 6 ]
is less than or
-le 5 <= 6 if test 5 -le 6 if expr [ 5 -le 6 ]
equal to
-gt is greater than 5>6 if test 5 -gt 6 if expr [ 5 -gt 6 ]
is greater than or
-ge 5 >= 6 if test 5 -ge 6 if expr [ 5 -ge 6 ]
equal to
Logical Operators
Logical operators are used to combine two or more condition at a time
Operator Meaning
! expression Logical NOT
expression1 -a expression2 Logical AND
expression1 -o expression2 Logical OR
(8)if...else...fi
If given condition is true then command1 is executed otherwise command2 is executed.
Syntax:
if condition
then
command1 if condition is true or if exit status
of condition is 0(zero)
...
...
else
command2 if condition is false or if exit status
of condition is >0 (nonzero)
...
...
fi
if test $1 -gt 0
then
echo "$1 number is positive"
else
echo "$1 number is negative"
fi
Try it as follows
$ chmod +x isnump_n
$ isnump_n 5
Here o/p : 5 number is positive
$ isnump_n -45
Here o/p : -45 number is negative
$ isnump_n
Here o/p : ./ispos_n : You must give/supply one integers
$ isnump_n 0
Here o/p : 0 number is negative
Here first we see if no command line argument is given then it print error message as "./ispos_n :
You must give/supply one integers". if statement checks whether number of argument ($#) passed
to script is not equal (-eq) to 0, if we passed any argument to script then this if statement is false
and if no command line argument is given then this if statement is true. The echo command i.e.
echo "$0 : You must give/supply one integers"
| |
| |
1 2
1 will print Name of script
2 will print this error message
And finally statement exit 1 causes normal program termination with exit status 1 (nonzero means
script is not successfully run), The last sample run $ isnump_n 0 , gives output as "0 number is
negative", because given argument is not > 0, hence condition is false and it's taken as negative
number. To avoid this replace second if statement with if test $1 -ge 0.
(9)Multilevel if-then-else
Syntax:
if condition
then
condition is zero (true - 0)
execute all commands up to elif statement
elif condition1
condition1 is zero (true - 0)
execute all commands up to elif statement
elif condition2
condition2 is zero (true - 0)
execute all commands up to elif statement
else
None of the above condtion,condtion1,condtion2 are true (i.e.
all of the above nonzero or false)
execute all commands up to fi
fi
For e.g. Write script as $ cat > elf #!/bin/sh # # Script to test if..elif...else # # if [ $1 -gt 0 ]
then echo "$1 is positive" elif [ $1 -lt 0 ] then echo "$1 is negative" elif [ $1 -eq 0 ]
then echo "$1 is zero" else echo "Opps! $1 is not number, give number" fi Try above
script with $ chmod +x elf $ ./elf 1 $ ./elf -2 $ ./elf 0 $ ./elf a Here o/p for last
sample run: ./elf: [: -gt: unary operator expected ./elf: [: -lt: unary operator expected ./elf: [: -eq:
unary operator expected Opps! a is not number, give number Above program gives error for last
run, here integer comparison is expected therefore error like "./elf: [: -gt: unary operator expected"
occurs, but still our program notify this thing to user by providing message "Opps! a is not number,
give number". (10)Loops in Shell Scripts
Computer can repeat particular instruction again and again, until particular condition satisfies. A
group of instruction that is executed repeatedly is called a loop.
(a) for loop Syntax:
Suppose,
$ cat > testfor
for i in 1 2 3 4 5
do
echo "Welcome $i times"
done
Run it as,
$ chmod +x testfor
$ ./testfor
The for loop first creates i variable and assigned a number to i from the list of number from 1 to 5,
The shell execute echo statement for each assignment of i. (This is usually know as iteration) This
process will continue until all the items in the list were not finished, because of this it will repeat 5
echo statements. for e.g. Now try script as follows
$ cat > mtable
#!/bin/sh
#
#Script to test for loop
#
#
if [ $# -eq 0 ]
then
echo "Error - Number missing form command line argument"
echo "Syntax : $0 number"
echo " Use to print multiplication table for given number"
exit 1
fi
n=$1
for i in 1 2 3 4 5 6 7 8 9 10
do
echo "$n * $i = `expr $i \* $n`"
done
(b)while loop
Syntax:
while [ condition ]
do
command1
command2
command3
..
....
done
Loop is executed as long as given condition is true. For eg. Above for loop program can be written
using while loop as
$cat > nt1
#!/bin/sh
#
#Script to test while statement
#
#
if [ $# -eq 0 ]
then
echo "Error - Number missing form command line argument"
echo "Syntax : $0 number"
echo " Use to print multiplication table for given number"
exit 1
fi
n=$1
i=1
while [ $i -le 10 ]
do
echo "$n * $i = `expr $i \* $n`"
i=`expr $i + 1`
done
case $variable-name in
pattern1) command
...
..
command;;
pattern2) command
...
..
command;;
patternN) command
...
..
command;;
*) command
...
..
command;;
esac
The $variable-name is compared against the patterns until a match is found. The shell then
executes all the statements up to the two semicolons that are next to each other. The default is *)
and its executed if no match is found. For eg. Create script as follows
$ cat > car
#
# if no vehicle name is given
# i.e. -z $1 is defined and it is NULL
#
# if no command line arg
if [ -z $1 ]
then
rental="*** Unknown vehicle ***"
elif [ -n $1 ]
then
# otherwise make first arg as rental
rental=$1
fi
case $rental in
"car") echo "For $rental Rs.20 per k/m";;
"van") echo "For $rental Rs.10 per k/m";;
"jeep") echo "For $rental Rs.5 per k/m";;
"bicycle") echo "For $rental 20 paisa per k/m";;
*) echo "Sorry, I can not gat a $rental for you";;
esac
Run it as follows
$ chmod +x sayH
$ ./sayH
This script first ask you your name and then waits to enter name from the user, Then user enters
name from keyboard (After giving name you have to press ENTER key) and this entered name
through keyboard is stored (assigned) to variable fname.
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
by users who are currently login. Note that You can't use $ date who for same purpose, you must
put semicolon in between date and who command.
© 1998-2000 FreeOS.com (I) Pvt. Ltd. All rights reserved.
We can copy old shell's variable to new shell (i.e. first shells variable to seconds shell), such variable is
know as Global Shell variable. To do this use export command
Syntax: export variable1, variable2,.....variableN
For e.g.
$ vech=Bus
$ echo $vech
Bus
$ export vech
$ /bin/bash
$ echo $vech
Bus
$ exit
$ echo $vech
Bus
Command Meaning
Create new local variable 'vech' with Bus as value
$ vech=Bus
in first shell
$ echo $vech Print the contains of variable vech
$ export vech Export first shells variable to second shell
Now load second shell in memory (Old shell's
$ /bin/bash variable is accessed from second shell, if they are
exported )
$ echo $vech Print the contains of variable vech
$ exit Exit from second shell return to first shell
$ echo $vech Print the contains of variable vech
-20
11
2
^D
$ sort < nos
-20
2
10
11
First we have created the file nos, then we have taken input from this file and sort command prints sorted
numbers. This is called input redirection. In Linux (And in C programming Language) your keyboard,
screen etc are treated as files. Following are name of such files
File Descriptors
Standard File Use Example
number
stdin 0 as Standard input Keyboard
stdout 1 as Standard output Screen
stderr 2 as Standard error Screen
By default in Linux every program has three files associated with it, (when we start our program these
three files are automatically opened by your shell) The use of first two files (i.e. stdin and stdout) , are
already seen by us. The last file stderr (numbered as 2) is used by our program to print error on screen.
You can redirect the output from a file descriptor directly to file with following
Syntax: file-descriptor-number>filename
For e.g.
$ rm bad_file_name111
rm: cannot remove `bad_file_name111': No such file or directory ,is the output (error) of the above
program. Now if we try to redirect this error-output to file, it can not be send to file
$ rm bad_file_name111 > er
Still it prints output on stderr as rm: cannot remove `bad_file_name111': No such file or directory, And if
you see er file as $ cat er , This file is empty, since output is send to error device and you can not redirect
it to copy this error-output to your file 'er'. To overcome this we have to use following command
$ rm bad_file_name111 2>er
Note that no space are allowed between 2 and >, The 2>er directs the standard error output to file. 2
number is default number of stderr file. Now consider another example, here we are writing shell script as
follows
$ cat > demoscr
if [ $# -ne 2 ]
then
echo "Error : Number are not supplied"
echo "Usage : $0 number1 number2"
exit 1
fi
ans=`expr $1 + $2`
echo "Sum is $ans"
Try it as follows
$ chmod +x demoscr
$ ./demoscr
Error : Number are not supplied
Usage : ./demoscr number1 number2
$ ./demoscr > er1
$ ./demoscr 5 7
Sum is 12
Here for first sample run , our script prints error message indicating that we have not given two number.
For second sample run, we have redirect output of our script to file, since it's error we have to show it to
user, It means we have to print our error message on stderr not on stdout. To overcome this problem
replace above echo statements as follows
echo "Error : Number are not supplied" 1>&2
echo "Usage : $0 number1 number2" 1>&2
Now if you run as
$ ./demoscr > er1
Error : Number are not supplied
Usage : ./demoscr number1 number2
It will print error message on stderr and not on stdout. The 1>&2 at the end of echo statement, directs
the standard output (stdout) to standard error (stderr) device.
Syntax: from>&destination
Functions
Function is series of instruction/commands. Function performs particular activity in shell. To define
function use following
Syntax:
function-name ( )
{
command1
command2
.....
...
commandN
return
}
Where function-name is name of you function, that executes these commands. A return statement will
terminate the function. For e.g. Type SayHello() at $ prompt as follows
$ SayHello()
{
echo "Hello $LOGNAME, Have nice computing"
return
}
Now to execute this SayHello() function just type it name as follows
$ SayHello
Hello xxxxx, Have nice computing
This way you can call your function. Note that after restarting your computer you will loss this SayHello()
function, since its created for that session only. To overcome this problem and to add you own function to
automat some of the day today life task, your function to /etc/bashrc file. Note that to add function to this
file you must logon as root. Following is the sample /etc/bashrc file with today() function , which is used
to print formatted date. First logon as root or if you already logon with your name (your login is not root),
and want to move to root account, then you can type following command , when asked for password type
root (administrators) password
$ su
password:
Now open file as ( Note your prompt is changed to # from $ to indicate you are root)
# vi /etc/bashrc
OR
# mcedit /etc/bashrc
At the end of file add following in /etc/bashrc file
#
# today() to print formatted date
#
# To run this function type today at the $ prompt
# Added by Vivek to show function in Linux
#
today()
{
echo This is a `date +"%A %d in %B of %Y (%r)"`
return
}
Save the file and exit it, after all this modification your file may look like as follows
# /etc/bashrc
#
# today() to print formatted date
#
# To run this function type today at the $ prompt
# Added by Vivek to show function in Linux
today()
{
echo This is a `date +"%A %d in %B of %Y (%r)"`
return
}
To run function first completely logout by typing exit at the $prompt (Or press CTRL + D, Note you may
have to type exit (CTRL +D) twice if you login to root account by using su command) ,then login and type
$ today , this way today() is available to all user in your system, If you want to add particular function to
particular user then open .bashrc file in your home directory as follows
# vi .bashrc
OR
# mcedit .bashrc
At the end of file add following in .bashrc file
SayBuy()
{
echo "Buy $LOGNAME ! Life never be the same, until you log again!"
echo "Press a key to logout. . ."
read
return
}
Save the file and exit it, after all this modification your file may look like as follows
# .bashrc
#
# User specific aliases and functions
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
SayBuy()
{
echo "Buy $LOGNAME ! Life never be the same, until you log again!"
echo "Press a key to logout. . ."
read
return
}
To run function first logout by typing exit at the $ prompt (Or press CTRL + D ) ,then logon and type $
SayBuy , this way SayBuy() is available to only in your login and not to all user in system, Use .bashrc
file in your home directory to add User specific aliases and functions only. (Tip: If you want to show some
message or want to perform some action when you logout, Open file .bash_logout in your home directory
and add your stuff here For e.g. When ever I logout, I want to show message Buy! Then open your
.bash_logout file using text editor such as vi and add statement
echo "Buy $LOGNAME, Press a key. . ."
read
Save and exit from the file. Then to test this logout from your system by pressing CTRL + D (or type exit)
immediately you will see message "Buy xxxxx, Press a key. . .", after pressing key you will be exited.)
done
Above all statement explained in following table
Statement Explanation
Start infinite loop, this loop will
only break if you select 5 ( i.e.
while :
Exit/Stop menu item) as your menu
choice
do Start loop
Clear the screen, each and every
clear
time
echo "-------------------------------------"
echo " Main Menu "
echo "-------------------------------------"
echo "[1] Show Todays date/time"
Show menu on screen with menu
echo "[2] Show files in current directory"
items
echo "[3] Show calendar"
echo "[4] Start editor to write letters"
echo "[5] Exit/Stop"
echo "======================="
Ask user to enter menu item
echo -n "Enter your menu choice [1-5]: "
number
read yourch Read menu item number from user
case $yourch in
1) echo "Today is `date` , press a key. . ." ; read ;;
2) echo "Files in `pwd`" ; ls -l ;
Take appropriate action according
echo "Press a key. . ." ; read ;;
to selected menu item, If menu item
3) cal ; echo "Press a key. . ." ; read ;;
is not between 1 - 5, then show
4) vi ;;
error and ask user to input number
5) exit 0 ;;
between 1-5 again
*) echo "Opps!!! Please select choice 1,2,3,4, or 5";
echo "Press a key. . ." ; read ;;
esca
Stop loop , if menu item number is
done
5 ( i.e. Exit/Stop)
User interface usually includes, menus, different type of boxes like info box, message box, Input box etc.
In Linux shell there is no built-in facility available to create such user interface, But there is one utility
supplied with Red Hat Linux version 6.0 called dialog, which is used to create different type of boxes like
info box, message box, menu box, Input box etc. Now try dialog utility as follows :
Above script creates yesno type dialog box, which is used to ask some questions to the user , and answer
to those question either yes or no. After asking question how do we know, whether user has press yes or
no button ? The answer is exit status, if user press yes button exit status will be zero, if user press no
button exit status will be one and if user press Escape key to cancel dialog box exit status will be one 255.
That is what we have tested in our above shell as
Statement Meaning
Get exit status of dialog
sel=$?
utility
Now take action according
case $sel in to exit status of dialog
0) echo "You select to delete file";; utility, if exit status is 0 ,
1) echo "You select not to delete file";; delete file, if exit status is
255) echo "Canceled by you by pressing [Escape] key";; 1 do not delete file and if
esac exit status is 255, means
Escape key is pressed.
sel=$?
na=`cat /tmp/input.$$`
case $sel in
0) echo "Hello $na" ;;
1) echo "Cancel is Press" ;;
255) echo "[ESCAPE] key pressed" ;;
esac
rm -f /tmp/input.$$
Inputbox is used to take input from user, Here we are taking Name of user as input. But where we are
going to store inputted name, the answer is to redirect inputted name to file via statement
2>/tmp/input.$$ at the end of dialog command, which means send screen output to file called
/tmp/input.$$, letter we can retrieve this inputted name and store to variable as follows
na=`cat /tmp/input.$$`. For inputbox exit status is as follows
Exit Status for Inputbox Meaning
0 Command is successful
1 Cancel button is pressed by user
255 Escape key is pressed by user
Now we will write script to create menus using dialog utility, following are menu items
Date/time
Calendar
Editor
and action for each menu-item is follows
-----------------------------------------------
MENU-ITEM ACTION
-----------------------------------------------
Date/time Show current date/time
Calendar Show calendar
Editor Start vi Editor
-----------------------------------------------
Create script as follows
$ cat > smenu
#
#How to create small menu using dialog
#
dialog --backtitle "Linux Shell Script Tutorial " --title "Main\
Menu" --menu "Move using [UP] [DOWN],[Enter] to\
Select" 15 50 3\
Date/time "Shows Date and Time"\
Calendar "To see calendar "\
Editor "To start vi editor " 2>/tmp/menuitem.$$
menuitem=`cat /tmp/menuitem.$$`
opt=$?
case $menuitem in
Date/time) date;;
Calendar) cal;;
Editor) vi;;
esac
rm -f /tmp/menuitem.$$
After creating menus, user selects menu-item by pressing enter key the selected choice is redirected to
temporary file, Next this menu-item is retrieved from temporary file and following case statement
compare the menu-item and takes appropriate step according to selected menu item. As you see, dialog
utility allows more powerful user interaction then the older read and echo statement. The only problem
with dialog utility is it work slowly.
trap command
Now consider following script
$ cat > testsign
ls -R /
Save and run it as
$ chmod +x testsign
$ ./testsign
Now if you press ctrl + c , while running this script, script get terminated. The ctrl + c here work as
signal, When such signal occurs its send to all process currently running in your system. Now consider
following shell script
if [ ! -f $filename ]; then
echo "Sorry, $filename does not exit, Creating $filename database"
echo "Appointment Note keeper Application database file" > $filename
fi
file. Then one infinite loop begins, which ask appointment title, time and remark, if this information is
correct its written to temporary file, After that script ask user , whether he/she wants add next
appointment record, if yes then next record is added , otherwise all records are copied from temporary file
to database file and then loop will be terminated. You can view your database file by using cat command.
Now problem is that while running this script, if you press CTRL + C, your shell script gets terminated and
temporary file are left in /tmp directory. For e.g. try as follows
$./testsign1
After given database file name and after adding at least one appointment record to temporary file press
CTRL+C, Our script get terminated, and it left temporary file in /tmp directory, you can check this by
giving command as follows
$ ls /tmp/input*
Our script needs to detect when such signal (event) occurs, To achieve this we have to first detect Signal
using trap command
Syntax: trap {commands} {signal number list}
Signal Number When occurs
0 shell exit
1 hangup
2 interrupt (CTRL+C)
3 quit
9 kill (cannot be caught)
To catch this signal in above script, put trap statement before calling Take_input1 function as trap
del_file 2 ., Here trap command called del_file() when 2 number interrupt ( i.e.CTRL+C ) occurs. Open
above script in editor and modify it so that at the end it will look like as follows
$ vi testsign1
or
$ mcedit testsign1
#
# signal is trapped to delete temporary file , version 2
#
del_file()
{
echo "* * * CTRL + C Trap Occurs (removing temporary file)* * *"
rm -f /tmp/input0.$$
exit 1
}
Take_input1()
{
recno=0
clear
echo "Appointment Note keeper Application for Linux"
echo -n "Enter your database file name : "
read filename
if [ ! -f $filename ]; then
echo "Sorry, $filename does not exit, Creating $filename database"
echo "Appointment Note keeper Application database file" > $filename
fi
getopts command
This command is used to check valid command line argument passed to script. Usually used in while loop.
Syntax: getopts {optsring} {variable1}
getopts is used by shell to parse command line argument. optstring contains the option letters to be
recognized; if a letter is followed by a colon, the option is expected to have an argument, which should
be separated from it by white space. Each time it is invoked, getopts places the next option in the shell
variable variable1, When an option requires an argument, getopts places that argument into the variable
OPTARG. On errors getopts diagnostic messages are printed when illegal options or missing option
arguments are encountered. If an illegal option is seen, getopts places ? into variable1. For e.g. We have
script called ani which has syntax as
ani -n -a -s -w -d
Options: These are optional argument
-n name of animal
-a age of animal
-s sex of animal
-w weight of animal
-d demo values (if any of the above options are used
their values are not taken)
$ cat > ani
#
# Usage: ani -n -a -s -w -d
#
#
# help_ani() To print help
#
help_ani()
{
echo "Usage: $0 -n -a -s -w -d"
echo "Options: These are optional argument"
echo " -n name of animal"
echo " -a age of animal"
echo " -s sex of animal "
echo " -w weight of animal"
echo " -d demo values (if any of the above options are used "
echo " their values are not taken)"
exit 1
}
#
#Start main procedure
#
#
#Set default value for variable
#
isdef=0
na=Moti
age="2 Months"
sex=Male
weight=3Kg
#
#if no argument
#
if [ $# -lt 1 ]; then
help_ani
fi
if [ $isdef -eq 0 ]
then
echo "Animal Name: $na, Age: $age, Sex: $sex, Weight: $weight (user define mode)"
else
na="Pluto Dog"
age=3
sex=Male
weight=20kg
echo "Animal Name: $na, Age: $age, Sex: $sex, Weight: $weight (demo mode)"
fi
See because of getopts, we can pass command line argument in different style. Following are invalid
options for ani script
$ ani -nLassie -a4 -sFemal -w20Kg
Here no space between option and their value.
$ ani -nLassie-a4-sFemal-w20Kg
$ ani -n Lassie -a 4 -s Female -w 20Kg -c Mammal
Here -c is not one of the options.
Q.11.Write script to determine whether given file exist or not, file name is supplied as command line
argument, also check for sufficient number of command line argument
Answer: See Q11 shell Script.
Q.12.Write script to determine whether given command line argument ($1) contains "*" symbol or not, if
$1 does not contains "*" symbol add it to $1, otherwise show message "Symbol is not required". For e.g.
If we called this script Q12 then after giving ,
$ Q12 /bin
Here $1 is /bin, it should check whether "*" symbol is present or not if not it should print Required i.e.
/bin/*, and if symbol present then Symbol is not required must be printed. Test your script as
$ Q12 /bin
$ Q12 /bin/*
Answer: See Q12 shell Script
Q.13. Write script to print contains of file from given line number to next given number of lines. For e.g. If
we called this script as Q13 and run as
$ Q13 5 5 myf , Here print contains of 'myf' file from line number 5 to next 5 line of that file.
Answer: See Q13 shell Script
Q.14. Write script to implement getopts statement, your script should understand following command line
argument called this script Q14,
Q14 -c -d -m -e
Where options work as
-c clear the screen
-d show list of files in current working directory
-m start mc (midnight commander shell) , if installed
-e { editor } start this { editor } if installed
Answer: See Q14 shell Script
Q.15. Write script called sayHello, put this script into your startup file called .bash_profile, the script
should run as soon as you logon to system, and it print any one of the following message in infobox using
dialog utility, if installed in your system, If dialog utility is not installed then use echo statement to print
message : -
Good Morning
Good Afternoon
Good Evening , according to system time.
Answer: See Q15 shell Script
Q.16. How to write script, that will print, Message "Hello World" , in Bold and Blink effect, and in different
colors like red, brown etc using echo command.
Answer: See Q16 shell Script
Q.17. Write script to implement background process that will continually print current time in upper right
corner of the screen , while user can do his/her normal job at $ prompt.
Answer: See Q17 shell Script.
Q.18. Write shell script to implement menus using dialog utility. Menu-items and action according to select
menu-item is as follows
Menu-Item Purpose Action for Menu-Item
Date and time must be shown using infobox of dialog
Date/time To see current date time
utility
Calendar To see current calendar Calendar must be shown using infobox of dialog utility
First ask user name of directory where all files are
present, if no name of directory given assumes current
directory, then show all files only of that directory, Files
must be shown on screen using menus of dialog utility,
Delete To delete selected file
let the user select the file, then ask the confirmation to
user whether he/she wants to delete selected file, if
answer is yes then delete the file , report errors if any
while deleting file to user.
Exit To Exit this shell script Exit/Stops the menu driven program i.e. this script
Note: Create function for all action for e.g. To show date/time on screen create function
show_datetime().
Answer: See Q18 shell Script.
Q.19. Write shell script to show various system configuration like
1) Currently logged user and his logname
2) Your current shell
3) Your home directory
4) Your operating system type
5) Your current path setting
6) Your current working directory
7) Show Currently logged number of users
8) About your os and version ,release number , kernel version
9) Show all available shells
10) Show mouse settings
11) Show computer cpu information like processor type, speed etc
12) Show memory information
13) Show hard disk information like size of hard-disk, cache memory, model etc
14) File system (Mounted)
Answer: See Q19 shell Script.
That's all!, Thanks for reading, This tutorial ends here, but Linux programming environment is big, rich
and productive (As you see from above shell script exercise), you should continue to read more advance
topics and books. If you have any suggestion or new ideas or problem with this tutorial, please feel free to
contact me.
My e-mail is gite-vivek@usa.net.
© 1998-2000 FreeOS.com (I) Pvt. Ltd. All rights reserved.