More Advanced Shell Script Commands

/dev/null - Use to send unwanted output of program

This is special Linux file which is used to send any unwanted output from program/command.


Syntax: command > /dev/null


For e.g. 
$ ls > /dev/null
, output of this command is not shown on screen its send to this special file. The /dev directory contains other device files. The files in this directory mostly represent peripheral devices such disks like floppy disk, sound card, line printers etc.

Local and Global Shell variable (export command)

Normally all our variables are local. Local variable can be used in same shell, if you load another copy of shell (by typing the /bin/bash at the $ prompt) then new shell ignored all old shell's variable. For e.g. Consider following example
$ vech=Bus
$ echo $vech
Bus
$ /bin/bash
$ echo $vech

NOTE:-Empty line printed
$ vech=Car
$ echo $vech
Car
$ exit
$ echo $vech
Bus

Command Meaning
$ vech=Bus Create new local variable 'vech' with Bus as value in first shell
$ echo $vech Print the contains of variable vech
$ /bin/bash Now load second shell in memory (Which ignores all old shell's variable)
$ echo $vech Print the contains of variable vech
$ vech=Car Create new local variable 'vech' with Car as value in second shell
$ 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 (Now you can see first shells variable and its value)

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
$ vech=Bus Create new local variable 'vech' with Bus as value in first shell
$ echo $vech Print the contains of variable vech
$ export vech Export first shells variable to second shell
$ /bin/bash Now load second shell in memory (Old shell's 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 


Conditional execution i.e. && and ||


The control operators are && (read as AND) and || (read as OR). The syntax for AND list is as follows
Syntax: command1 && command2

Here command2 is executed if, and only if, command1 returns an exit status of zero. 

The syntax for OR list as follows 
Syntax: command1 || command2


Here command2 is executed if and only if command1 returns a non-zero exit status. You can use both as follows
Syntax:
command1 && comamnd2 if exist status is zero || command3 if exit status is non-zero


Here if command1 is executed successfully then shell will run command2 and if command1 is not successful then command3 is executed. 
For e.g.
$ rm  myf && echo "File is removed successfully"  ||  echo "File is not removed"

If file (myf) is removed successful (exist status is zero) then "echo File is removed successfully" statement is executed, otherwise "echo File is not removed" statement is executed (since exist status is non-zero)

I/O Redirection and file descriptors

As you know I/O redirectors are used to send output of command to file or to read input from file. Now consider following examples
$ cat > myf
     This is my file
     ^D
Above command send output of cat command to myf file
$ cal
Above command prints calendar on screen, but if you wish to store this calendar to file then give command
$ cal > mycal
The cal command send output to mycal file. This is called output redirection
$ sort
10
-20
11
2
^D
-20
2
10
11
Here sort command takes input from keyboard and then sorts the number, If we wish to take input from file give command as follows
$ cat > nos
10
-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

Standard File File Descriptors number Use Example
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
Example
$ 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 755  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 function. Note that after restarting your computer you will loss this SayHello() function, since its created for current session only. To overcome this problem and to add you own function to automat some of the day today life task, add 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 -l
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

# System wide functions and aliases
# Environment stuff goes in /etc/profile

# For some unknown reason bash refuses to inherit
# PS1 in some circumstances that I can't figure out.
# Putting PS1 here ensures that it gets loaded every time.

PS1="[\u@\h \W]\\$ "

#
# 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 users  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.)

User Interface and dialog utility


Good program/shell script must interact with users. There are two ways to this one is use command line to script when you want input, second use statement like echo and read to read input into variable from the prompt. For e.g. Write script as

$ cat > userinte
#
# Script to demo echo and read command for user interaction
#
echo "Your good name please :"
read na
echo "Your age please :"
read age
neyr=`expr $age + 1`
echo "Hello $na, next year you will be $neyr yrs old."


Save it and run as
$ chmod 755 userinte
$ ./userinte

Your good name please :
Vivek
Your age please :
25
Hello Vivek, next year you will be 26 yrs old.

Even you can create menus to interact with user, first show menu option, then ask user to choose menu item, and take appropriate action according to selected menu item, this technique is show in following script

$ cat > menuui
#
# Script to create simple menus and take action according to that selected
# menu item
#
while :
do
       clear
       echo "-------------------------------------"
       echo " Main Menu "
       echo "-------------------------------------"
       echo "[1] Show Todays date/time"
       echo "[2] Show files in current directory"
       echo "[3] Show calendar"
       echo "[4] Start editor to write letters"
       echo "[5] Exit/Stop"
       echo "======================="
       echo -n "Enter your menu choice [1-5]: "
       read yourch
     case $yourch in
           1) echo "Today is `date` , press a key. . ." ; read ;;
           2) echo "Files in `pwd`" ; ls -l ; echo "Press a key. . ." ; read ;;
           3) cal ; echo "Press a key. . ." ; read ;;
           4) vi ;;
           5) exit 0 ;;
           *) echo "Opps!!! Please select choice 1,2,3,4, or 5";
             echo "Press a key. . ." ; read ;;
     esac

done

Above all statement explained in following table
Statement Explanation
while : Start infinite loop, this loop will only break if you select 5 ( i.e. Exit/Stop menu item) as your menu choice
do Start loop
clear Clear the screen, each and every time 
echo "-------------------------------------"  
echo "                   Main Menu "
echo "-------------------------------------"
echo "[1] Show Todays date/time"  
echo "[2] Show files in current directory"
echo "[3] Show calendar"
echo "[4] Start editor to write letters"
echo "[5] Exit/Stop"
echo "======================="
Show menu on screen with menu items
echo -n "Enter your menu choice [1-5]: "
Ask user to enter menu item 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  ;  
      echo    "Press a key. . ." ; read ;;
3) cal ; echo "Press a key. . ." ; read ;;
4) vi ;;
5) exit 0 ;;
*) echo "Opps!!! Please select choice 1,2,3,4, or 5";
     echo "Press a key. . ." ; read  ;;
 
esac
Take appropriate action according to selected menu item, If menu item is not between 1 - 5, then show error and ask user to input number between 1-5 again
done Stop loop , if menu item number is 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 :

$ cat > dia1
dialog --title  "Linux Dialog Utility Infobox"  --backtitle  "Linux Shell Script\
Tutorial"  --infobox  "This is dialog box called infobox, which is used\
to show some information on screen, Thanks to Savio Lam and\
Stuart Herbert to give us this utility. Press any key. . . " 7 50 ; read

Save the shell script and run as
$ chmod +x dia1
$ ./dia1

After executing this dialog statement you will see box on screen with titled as "Welcome to Linux Dialog Utility" and message "This is dialog....Press any key. . ." inside this box. The title of box is specified by --title option and info box with --infobox "Message" with this option. Here 7 and 50 are height-of-box and width-of-box respectively. "Linux Shell Script Tutorial" is the backtitle of dialog show on upper left side of screen and below that line is drawn. Use dialog utility to Display dialog boxes from shell scripts.
Syntax:


        dialog --title {title} --backtitle {backtitle} {Box options}
        where Box options can be any one of following
        --yesno      {text}  {height} {width}
        --msgbox     {text}  {height} {width}
        --infobox    {text}  {height} {width}
        --inputbox   {text}  {height} {width} [{init}]
        --textbox    {file}  {height} {width}
        --menu       {text}  {height} {width} {menu} {height} {tag1} item1}...


msgbox using dialog utility

$cat > dia2
dialog --title "Linux Dialog Utility Msgbox"  --backtitle  "Linux Shell Script\
Tutorial" --msgbox "This is dialog box called msgbox, which is used\
to show some information on screen which has also Ok button, Thanks to Savio Lam\
and Stuart Herbert to give us this utility. Press any key. . . " 9 50


Save it and run as
$ chmod +x dia2
$ ./dia2

yesno box using dialog utility

$ cat > dia3
dialog --title "Alert : Delete File" --backtitle "Linux Shell Script\
Tutorial" --yesno "\nDo you want to delete '/usr/letters/jobapplication'\
file" 7 60
sel=$?
case $sel in
     0) echo "User select to delete file";;
     1) echo "User select not to delete file";;
     255) echo "Canceled by user by pressing [ESC] key";;
esac


Save it and run as
$ chmod +x dia3
$ ./dia3


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 script as

Statement Meaning
sel=$? Get exit status of dialog utility
case $sel in 
0) echo "You select to delete file";;
1) echo "You select not to delete file";;
255) echo "Canceled by you by pressing [Escape] key";;
esac
Now take action according to exit status of dialog utility, if exit status is 0 , delete file, if exit status is 1 do not delete file and if exit status is 255, means Escape key is pressed. 

inputbox using dialog utility
$ cat > dia4
dialog --title "Inputbox - To take input from you" --backtitle "Linux Shell\
Script Tutorial" --inputbox "Enter your name please" 8 60 2>/tmp/input.$$

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

dialog - Putting it all together

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


Save it and run as
$ rm -f /tmp/menuitem.$$
$ chmod +x smenu
$ ./smenu
H

ere --menu option is used of dialog utility to create menus, menu option take

--menu options Meaning
"Move using [UP] [DOWN],[Enter] to  Select" This is text show before menu
15  Height of box
50  Width of box
3   Height of menu
Date/time    "Shows Date and Time" First menu item called as tag1 (i.e. Date/time) and description for menu item called as item1 (i.e. "Shows Date and Time")

Calendar      "To see calendar    "
First menu item called as tag2 (i.e. Calendar) and description for menu item called as item2 (i.e. "To see calendar")
Editor           "To start vi editor " First menu item called as tag3 (i.e. Editor) and description for menu item called as item3 (i.e."To start vi editor")
2>/tmp/menuitem.$$ Send sleeted menu item (tag) to this temporary file
 

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

$ cat > testsign1
#
# Why to trap signal,  version 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          

echo  "Data entry start data: `date`" >/tmp/input0.$$
#
# Set a infinite loop
#
while :
do
     echo -n "Appointment Title:"
     read na
     echo -n "Appoint time :" 
     read ti
     echo -n "Any Remark :"
     read remark
     echo -n "Is data okay (y/n) ?"
     read ans

 if [ $ans = y -o $ans = Y ]; then
     recno=`expr $recno + 1`
     echo "$recno. $na $ti $remark" >> /tmp/input0.$$
 fi

    echo -n "Add next appointment (y/n)?"
     read isnext

  if [ $isnext = n -o $isnext = N ]; then
    cat /tmp/input0.$$ >> $filename
    rm -f /tmp/input0.$$
    return  # terminate loop
 fi
 done 
}

#
#
# Call our user define function : Take_input1
#
Take_input1

Save it and run as
$ chmod +x testsign1
$ ./testsign1

It first ask you main database file where all appointment of the day is stored, if no such database file found, file is created, after that it open one temporary file in /tmp directory, and puts today's date in that 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 asks 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 such signal (event) when 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 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          

echo  "Data entry start data: `date`" >/tmp/input0.$$
#
# Set a infinite loop
#
while :
do
     echo -n "Appointment Title:"
     read na
     echo -n "Appoint time :" 
     read ti
     echo -n "Any Remark :"
     read remark
     echo -n "Is data okay (y/n) ?"
     read ans

 if [ $ans = y -o $ans = Y ]; then
     recno=`expr $recno + 1`
     echo "$recno. $na $ti $remark" >> /tmp/input0.$$
 fi

    echo -n "Add next appointment (y/n)?"
     read isnext

  if [ $isnext = n -o $isnext = N ]; then
    cat /tmp/input0.$$ >> $filename
    rm -f /tmp/input0.$$
    return  # terminate loop
 fi
 done 
}

#
# Set trap to for CTRL+C interrupt, 
# When occurs it first it calls del_file() and then exit 
#
trap  del_file   2 

#
# Call our user define function : Take_input1
#
Take_input1

Now save it run the program as
$ ./testsign1


After giving database file name and after giving appointment title press CTRL+C, Here we have already captured this CTRL + C signal (interrupt), so first our function del_file() is called, in which it gives message as "* * * CTRL + C Trap Occurs (removing temporary file)* * * "  and then it remove our temporary file and then exit with exit status 1. Now check /tmp directory as follows
$ ls /tmp/input*
Now Shell will report no such temporary file exit.

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)

$ vi  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

while getopts n:a:s:w:d  opt 
do
        case "$opt" in
        n) na="$OPTARG";;
         a) age="$OPTARG";;
        s) sex="$OPTARG";;
       w) weight="$OPTARG";;
       d) isdef=1;;
     \?) help_ani;;    
    esac
done    

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

Save it and run as follows
$ chmod  +x  ani
$ ani  -n Lassie -a 4  -s Female  -w 20Kg
$ ani  -a 4  -s Female -n Lassie  -w 20Kg
$ ani  -n Lassie -s Female  -w 20Kg -a 4  
$ ani  -w 20Kg -s Female  -n Lassie -a 4   
$ ani  -w 20Kg -s Female  
$ ani  -n Lassie -a 4  
$ ani  -n Lassie 
$ ani  -a 2
 
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.