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) |
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 |
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 }
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"
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}...
$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. |
$ 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 |
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 # |
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 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.
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 na=Moti |
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.