Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Shell Script (Nigam&deepesh221110)

Download as pdf or txt
Download as pdf or txt
You are on page 1of 151

Shell script to check whether a String is Palindrome or

not?
This Shell Script is developed using Bourne Shell.
1=0
cnt=1
tag=0
echo "Enter a String?"
read str
1 =`echo $str |wc -c`
1 =`expr $l - 1`
1h=`expr $l / 2`
while [ $cnt -le $lh ]
do
c1=`echo $str|cut -c$cnt`
c2=`echo $str|cut -c$l`
if [ $c1 != $c2 ]
then
cnt=$lh
tag=1
fi
cnt=`expr $cnt + 1`
=`expr $l - 1`
done
if [ $tag -eq 0 ]
then
echo "String is Palindrome"
else
echo “String is not Palindrome”
fi

to reverse a string - method I


**************************
*****
Code:
str="program"
echo $str | awk '{
for(i=length($0);i>=1;i--)
printf("%s",substr($0,i,1));
}'

to reverse a string - method II


********************************

Code:
str="program"
i=${#str}
final=""

while [ $i -gt 0 ]
do
rev=`echo $str | awk '{printf substr($0, '$i', 1)}'`
final=$final$rev
i=$(($i - 1))
done

echo "Reversed String: $final"

to reverse a line
*************************************
Code:
str="this script is to reverse"
i=${#str}
word=""
fin=""
final=""

while [ $i -ge 0 ]
do
temp=`echo $str | awk '{printf substr($0, '$i', 1)}'`
if [ \( "$temp" = " " \) -o $i -eq 0 ]
then
wordlen=${#word}
while [ $wordlen -gt 0 ]
do
revtemp=`echo $word | awk '{printf substr($0, '$wordlen', 1)}'`
fin=$fin$revtemp
wordlen=$(($wordlen -1))
done
final=$final$fin" "
fin=""
word=""
temp=""
else
word=$word$temp
fi
i=$(($i - 1))
done

echo "Reversed line: $final"

to reverse a string
Code:
[~/temp]$ cat deepak.sh
#! /bin/sh

# reverse a string

[[ -z "$@" ]] && STR=" a b c d e f g h i j k l m n o p q r s t u v w x y z "


|| STR="$@"

len=${#STR}

REV=""
for (( i=$len ; i>0 ; i-- ))
do
REV=$REV""${STR:$i-1:$i}
STR=${STR%${STR:$i-1:$i}}
done

echo "Reversed string"


echo $REV

Code:
[~/temp]$ ./deepak.sh
Reversed string
z y x w v u t s r q p o n m l k j i h g f e d c b a

As for trimming, you can trim the leading and trailing white spaces.

Use this constuct within the script.

Code:
# remove leading white spaces
REV=${REV## }
# remove trailing white spaces
REV=${REV%% }

Write a shell program to find


Fibonacci series of a number.?
#!/bin/sh

echo -n "Enter How many numbers:"


read num

num1=0
num2=1

echo -n "Fibonacci series: "


echo -n $num1
echo -n " $num2"

count=2

while [ $count -le $num ]


do
num3=`expr $num1 + $num2`
echo -n " $num3 "
num1=$num2
num2=$num3
count=`expr $count + 1`
done

echo -e "\nFinished....."

Fibonacci number
Now we will run a script which calculates n-th Fibonacci number where n will be provided as
input when prompted.

User input 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Output 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181

Here is the script:

#!/bin/bash
# Fibonacci number shell script
# It takes input one number and show Fibonacci
number of that serial

# Prompts for an input


echo -n "Which fibonacci number do u want to
see? "
# Read the number
read nSerial

# Initializes variables
a=0
b=1
count=2 # Used to control the number of iteration
of the while loop
fibonacci_number=$a

# The loop to calculate the number


while [ $count -le $nSerial ]; do # Checks whether
count is less than or equal to nSerial
fibonacci_number=$[$a+$b]
a=$b
b=$fibonacci_number
count=$[$count + 1]
done

# Print the output


echo "Fibonacci $nSerial = $fibonacci_number"

Type the script in the editor and save the file as fib.sh. Run it after assinging execute permission:

{cs1:~} chmod +x fib.sh


{cs1:~} fib.sh
Which fibonacci number do u want to see? 5
Fibonacci 5 = 5

Enter any number you wish when prompted.

Fibonacci number of multiple values


Now, we will write a script which will calculate n-th Fibonacci number for multiple n's. The
script will prompt for an input until -1 is entered. After each input, it will show n-th Fibonacci
number.

#!/bin/bash
# Fibonacci number shell script
# It takes input multiple numbers and show Fibonacci
number of those serial
# It stops taking input when -1 is given

# Prompts for an input


echo -n "Which fibonacci number do u want to see?
(Enter -1 to exit) "
# Read the number
read nSerial

# Loops until -1 is given as input


while [ $nSerial -ne -1 ]; do # Checks whether nSerial
is not equal to -1
# Initializes variables
a=0
b=1
count=2 # Used to control the number of
iteration of the while loop
fibonacci_number=$a

# The loop to calculate the number


while [ $count -le $nSerial ]; do # Checks
whether count is less than or equal to nSerial
fibonacci_number=$[$a+$b]
a=$b
b=$fibonacci_number
count=$[$count + 1]
done

# Print the output


echo "Fibonacci $nSerial = $fibonacci_number"

# Prompts for an input


echo -n "Which fibonacci number do u want to
see? (Enter -1 to exit) "

# Read the number


read nSerial
done

Type the script in editor and save as fib_m.sh. Run after assigning execute permission:

{cs1:~} chmod +x fib_m.sh


{cs1:~} fib_m.sh
Which fibonacci number do u want to see? (Enter -1 to exit) 3
Fibonacci 3 = 2
Which fibonacci number do u want to see? (Enter -1 to exit) 10
Fibonacci 10 = 55
Which fibonacci number do u want to see? (Enter -1 to exit) -1

Enter any number you wish. To exit, enter -1.


Fibonacci number of one value read from file
This script will work similarly to our first Fibonacci example except that it will take input from a
file containing a number. The filename should be supplied by command line argument.

#!/bin/bash
# Fibonacci number shell script
# It takes input one number from a file and shows
Fibonacci number of that serial

# Checks whether user provided one file name.


# If the check fails, it prints and error message
and exits
# with an error code of 1
if [ $# -ne 1 ]; then
echo $0: Please provide a file name
exit 1
fi

# Initialize variables
a=0
b=1
count=2 # Used to control the number of iteration
of the while loop
fibonacci_number=$a

# Reads the file to variable end, filename is stored


in command line
# argument $1
read end < $1

# The loop to calculate the number


while [ $count -le $end ]; do # Checks whether
count is less than or equal to end
fibonacci_number=$[$a+$b]
a=$b
b=$fibonacci_number
count=$[$count + 1]
done

# Print the output


echo "Fibonacci $end = $fibonacci_number"

Type the script in editor and save as fib_f.sh. Before running the script create a file containing a
single number. Suppose, we create the file named fib.in. Run the script after assigning execute
permission:
{cs1:~} echo 11 > fib.in
{cs1:~} chmod +x fib_f.sh
{cs1:~} fib_f.sh fib.in
Fibonacci 11 = 89

Fibonacci number of multiple values read from file


Now, we will write a script which will read multiple values from a file. The file should contain
multiple values, each value in separate lines. The filename should be supplied by command line
argument.

#!/bin/bash
# Fibonacci number shell script
# It takes input more than one number from a file
each residing in a single line
# and shows Fibonacci number of that serial

# Checks whether user provided one file name.


# If the check fails, it prints and error message and
exits
# with an error code of 1
if [ $# -ne 1 ]; then
echo $0: Please provide a file name
exit 1
fi

# Read value into "end" until end of file


while read end; do

# Initialize variables
a=0
b=1
count=2 # Used to control the number of
iteration of the while loop
fibonacci_number=$a

# The loop to calculate the number


while [ $count -le $end ]; do # Checks whether
count is less than or equal to end
fibonacci_number=$[$a+$b]
a=$b
b=$fibonacci_number
count=$[$count + 1]
done

# Print the output


echo "Fibonacci $end = $fibonacci_number"

done < $1 # Input from file $1

Type the script in editor and save as fib_m_f.sh. Here is a sample input file fib_m.in containing
values 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 and 20. Right-click the link and save the file in appropriate
location. Run the script after assigning execute permission:

{cs1:~} chmod +x fib_m_f.sh


{cs1:~} fib_m_f.sh fib_m.in
Fibonacci 0 = 0
Fibonacci 1 = 1
Fibonacci 2 = 1
Fibonacci 3 = 2
Fibonacci 4 = 3
Fibonacci 5 = 5
Fibonacci 6 = 8
Fibonacci 7 = 13
Fibonacci 8 = 21
Fibonacci 9 = 34
Fibonacci 10 = 55
Fibonacci 20 = 6765

Exercise
In the first Fibonacci script, add error check on the input for negative integers and real numbers
as they are not defined in the series. If user inputs such number the output should be "not
defined". For example:

Fibonacci -1 = not defined


Fibonacci -11 = not defined
Fibonacci 6.89 = not defined
Fibonacci -99.127 = not defined
Shell Scripting
Showing newest posts with label Shell Scripts. Show older posts

Showing newest posts with label Shell Scripts. Show older posts

Saturday, July 31, 2010


Shell Script to Check Whether a String is Palindrome or not

Palindrome: A palindrome is a word, phrase, number or other


sequence
of units that can be read the same way in either direction (the
adjus-
tment of punctuation and spaces between words is generally
permitted).

Examples:

Phrases: Dammit, I'm mad!


Quotations: Able was I ere I saw Elba.
Madam, I'm Adam.
Names: Some people have names that are palindromes.Lon Nol
(1913-
1985) was Prime Minister of Cambodia.
Palindromic names are very common in Finland. Examples
include Emma Lamme,Sanna Rannas, Anni Linna and Asko
Oksa.
Words: civic,radar,level,rotator,rececar,reviver.
The command "Level, madam, level!", composed only of
words
that are themselves palindromes, is both a character-
by-
character and a word-by-word palindrome.
Numbers: 5335, 123454321
Dates: 01/02/2010 (dd/mm/yyyy format)

Method 1:

#!/bin/bash
# SCRIPT: palindrome1.sh
# USAGE: palindrome.sh or palindrome.sh STRING
# PURPOSE: Script to test if a given string is a palindrome.
#
# In this script I uses the well known method, compare first
character
# with last character, up to middle of the string. One mismatch in
the
# scanning leads to immediate termination of the scanning as it is
# not a palindrome. To extract character from string, I will use
cut
# command with the -c option with the position number.
#
###################################################################
##
# Arguments Checking
#
###################################################################
##

if [ $# -eq 0 ]
then
echo -n "Enter a String: "
read orgstr
else
orgstr=$*
fi

# You can also use single statement


#[ $# -eq 0 ] && (echo -n "Enter a String:"; read String) ||
String=$*

###################################################################
##
# Variable Initialization
#
###################################################################
##

# Remove all punctuations from input string and convert upper case
to
# lower or lower case to upper.

String="$(echo $orgstr | sed 's/[^[:alnum:]]//g' | \


tr '[:upper:]' '[:lower:]')"

Flag=0

# Find length of the string.


len=${#String}

#You can also calculate string length using bellow commands.


#len=`echo $str | wc -c`
#len=$((len-1))

#get the mid value up to which the comparison would be done.


mid=$((len/2))
###################################################################
##
# Main Script Starts Here
#
###################################################################
##

for ((i=1;i<=mid;i++))
do
c1=`echo $String|cut -c$i` # extracts from beginning
c2=`echo $String|cut -c$len` # extracts from last

if [ $c1 != $c2 ]
then
Flag=1

break 2 # break N breaks out of N levels of


loop.
fi

let len--
done

if [ $Flag -eq 0 ]
then
echo "\"$orgstr\" is a Palindrome"
else
echo "\"$orgstr\" is not a Palindrome"
fi

OUTPUT:

[root@www ]# ./palindrome1.sh Dammit, I\'m mad!


"Dammit, I'm mad!" is a Palindrome
[root@www ]# ./palindrome1.sh
Enter a String: 01/02/2010
"01/02/2010" is a Palindrome
[root@www ]# ./palindrome1.sh Hello world
"Hello world" is not a Palindrome

Method 2:

#!/bin/bash
# SCRIPT: palindrome2.sh
# USAGE: palindrome.sh or palindrome.sh STRING
# PURPOSE: Script to test if a given string is a palindrome.
#
# In this script I uses the well known method, compare first
character
# with last character, up to middle of the string. One mismatch in
the
# scanning leads to immediate termination of the scanning as it is
# not a palindrome. To extract a character from the string, I will
use
# string manipulation operations.So you need to know how to
manipulate
# strings to understand this script. I will give little bit of
explan-
# tion at the end of this script.
#
###################################################################
##
# Arguments Checking
#
###################################################################
##

[ $# -eq 0 ] && { echo -n "Enter a String: "; read orgstr ;} || \


orgstr=$*

###################################################################
##
# Variable Initialization
#
###################################################################
##

# Remove all punctuations from input string and convert upper case
to
# lower or lower case to upper.

String="$(echo $orgstr | sed 's/[^[:alnum:]]//g' | \


tr '[:upper:]' '[:lower:]')"

# Find length of the string.


len=${#String}

#get the mid value up to which the comparison would be done


mid=$(($len/2))

i=0
Flag=0

###################################################################
##
# Main Script Starts Here
#
###################################################################
##

while [ $i -lt $mid ]


do
fchar=${String:$i:1}
let i++
bchar=${String: -$i:1}
if [ "$fchar" != $bchar ]
then
Flag=1
break 2 # break N breaks out of N levels of
loop.
fi
done

if [ $Flag -eq 0 ]
then
echo "\"$orgstr\" is a Palindrome"
else
echo "\"$orgstr\" is not a Palindrome"
fi

Substring Extraction:

${string:position}
Extracts substring from $string at $position.
${string:position:length}
Extracts $length characters of substring from $string at
$position

Bash numbers first character of string as '0'.

${string: 0: 1} will extracts one character from the 0th character


of
the string, ie it will only get the 0th character. ${string: 2: 1}
will get the third character. Also ${string: -1: 1} will extracts
the
last one character, ${string: -3:1} will get the third last
character.

Note: ${string: -1:1} in this construct don't forget to give space


before -1, otherwise you will get full string.

For example
[root@localhost www]# tempvar=madam
[root@localhost www]# echo ${tempvar: -1:1}
m
[root@localhost www]# echo ${tempvar:-1:1}
madam

You can also use following command

[root@localhost www]# echo ${tempvar:(-1):1}


m

OUTPUT:

[root@www ]# ./palindrome2.sh Able was I ere I saw Elba


"Able was I ere I saw Elba" is a Palindrome
[root@www ]# ./palindrome2.sh 123454321
"123454321" is a Palindrome
[root@www ]# ./palindrome2.sh
Enter a String: 12345654321
"12345654321" is a Palindrome
[root@www ]# ./palindrome2.sh
Enter a String: 1234564321
"1234564321" is not a Palindrome

Method 3:

#!/bin/bash
# SCRIPT: palindrome3.sh
# USAGE: palindrome.sh or palindrome.sh STRING
# PURPOSE: Script to test if a given string is a palindrome.
#
# This simply uses the 'rev' utility which is used to reverse lines
of
# a file. Then check if the reverse of the string is same as the
# original.rev command is part of util-linux-ng or util-linux
package.
#

if `which rev &>/dev/null` # Checks rev command exist or not


then
[ $# -eq 0 ] && { echo -n "Enter a String: "; read orgstr ;}
|| \
orgstr=$*

String="$(echo $orgstr | sed 's/[^[:alnum:]]//g' | \


tr '[:upper:]' '[:lower:]')"

if [ "$(echo $String | rev)" = "$String" ]


then
echo "\"$orgstr\" is a palindrome"
else
echo "\"$orgstr\" is not a palindrome"
fi

else
echo "Install util-linux or util-linux-ng package"
fi

OUTPUT:

[root@www ]# ./palindrome3.sh 01/02/2010


"01/02/2010" is a palindrome
[root@www ]# ./palindrome3.sh 01/03/2010
"01/03/2010" is not a palindrome
[root@www ]# ./palindrome3.sh
Enter a String: Hello World
"Hello World" is not a palindrome
[root@www ]# ./palindrome3.sh
Enter a String: rotator
"rotator" is a palindrome

Method 4:

#!/bin/bash
# SCRIPT: palindrome4.sh
# USAGE: palindrome.sh or palindrome.sh STRING
# PURPOSE: Script to test if a given string is a palindrome.
#
# In this method we are not using 'rev' command to reverse the
string.
# Using Substring Removal method or Substring Extraction method we
# will reverse the string, then compare it with oldstring.
#
###################################################################
##
# Arguments Checking
#
###################################################################
##

[ $# -eq 0 ] && { echo -n "Enter a String: "; read orgstr ;} || \


orgstr=$*

###################################################################
##
# Variable Initialization
#
###################################################################
##

String="$(echo $orgstr | sed 's/[^[:alnum:]]//g' | \


tr '[:upper:]' '[:lower:]')"

oldstring=$String
newstring=

###################################################################
##
# Main Script Starts Here
#
###################################################################
##

while [ -n "$String" ]
do
temp=${String#?}
letter=${String%"$temp"}
String=$temp
newstring=${letter}${newstring}
done

if [ "$oldstring" = "$newstring" ]
then
echo "\"$orgstr\" is a palindrome"
else
echo "\"$orgstr\" is not a palindrome"
fi

# ${string#substring} is a Substing Removal operation. If you want


to
# use Substring Extraction method, use bellow code.

#i=0
#while [ $i -lt ${#String} ]
#do
# letter=${String:$i:1}
# newstring=${letter}${newstring}
# let i++;
#done
#
#if [ "$String" = "$newstring" ]
#then
# echo "\"$orgstr\" is a palindrome"
#else
# echo "\"$orgstr\" is not a palindrome"
#fi

Substring Removal:

${string#substring}
Strips shortest match of $substring from front of $string.

Example:

[root@www]# tempvar=madam
[root@www]# echo ${tempvar#m}
adam
[root@www]# echo ${tempvar#ma}
dam
[root@www]# echo ${tempvar#?}
adam

${string%substring}
Strips shortest match of $substring from back of $string.

Example:

[root@www]# temp=${tempvar#?}
[root@www]# echo $temp
adam
[root@www]# echo ${tempvar%$temp}
m

OUTPUT:

[root@www ]# ./palindrome4.sh Madam, I\'m Adam


"Madam, I'm Adam" is a palindrome
[root@www ]# ./palindrome4.sh Madam I Adam
"Madam I Adam" is not a palindrome
[root@www ]# ./palindrome4.sh
Enter a String: 123454321
"123454321" is a palindrome
[root@www ]# ./palindrome4.sh
Enter a String: 1234564321
"1234564321" is not a palindrome

Posted by venu k at 4:18 PM 0 comments

Labels: Shell Scripts


Thursday, July 29, 2010
Insertion Sort Shell Script

#!/bin/bash#!/bin/bash
# SCRIPT: insertionsort.sh
#
# LOGIC: Here, sorting takes place by inserting a particular
element
# at the appropriate position, that’s why the name insertion
sorting.
# In the First iteration, second element ARRAY[1] is compared with
# the first element ARRAY[0]. In the second iteration third element
# is compared with first and second element. In general, in every
# iteration an element is compared with all the elements before it.
# While comparing if it is found that the element can be inserted
at
# a suitable position, then space is created for it by shifting the
# other elements one position up and inserts the desired element at
# the suitable position. This procedure is repeated for all the
# elements in the list.
#
###################################################################
##
# Define Functions Here
#
###################################################################
##

printnumbers()
{
echo ${ARRAY[*]}
}

sortnumbers()
{
for((i=1;i<count;i++))
do
Temp=${ARRAY[i]}
j=$((i-1))
while [ $Temp -lt ${ARRAY[j]} ]
do
ARRAY[j+1]=${ARRAY[j]}
let j--
if [ $j == -1 ]
then
break
fi
done
ARRAY[j+1]=$Temp
done
}

###################################################################
##
# Variable Initialization
#
###################################################################
##

echo "Enter numbers to be sorted"

read -a ARRAY

count=${#ARRAY[@]}

###################################################################
##
# Main Script Starts Here
#
###################################################################
##

echo "-------------------------------------------------------------
--"

echo "Numbers Before Sort:"

printnumbers

sortnumbers

echo "Numbers After Sort: "

printnumbers

echo "-------------------------------------------------------------
--"

OUTPUT:

[root@www blog]# sh insertionsort.sh


Enter Numbers to be Sorted :
12 76 34 -34 67 9 -56 5 99 -3 17
---------------------------------------------------------------
Numbers Before Sort:
12 76 34 -34 67 9 -56 5 99 -3 17
Numbers After Sort:
-56 -34 -3 5 9 12 17 34 67 76 99
---------------------------------------------------------------

NOTE: If we complement the while condition in this program, it will


give out the sorted array in descending order.

Posted by venu k at 9:34 AM 1 comments

Labels: Shell Scripts

Selection Sort Shell Script

#!/bin/bash#!/bin/bash
# SCRIPT: selectionsort.sh
#
# LOGIC : Here, to sort the data in ascending order, the first
element
# ARRAY[0] is compared with all the other elements till the end of
the
# array. If it is greater than any other the elements then they are
# interchanged. So after the first iteration of the outer for loop
# smallest element will be placed at the first position. The same
pro-
# cedure is repeated for the other elements too.
#
###################################################################
##
# Define Functions Here
#
###################################################################
##

printnumbers()
{
echo ${ARRAY[*]}
}

swap()
{
temp=${ARRAY[$1]}

ARRAY[$1]=${ARRAY[$2]}

ARRAY[$2]=$temp
}

sortnumbers()
{
for ((i=0;i<count;i++))
do
min=$i
for ((j=i+1;j<count;j++))
do
if [ ${ARRAY[j]} -lt ${ARRAY[min]} ]
then
min=$j
fi
done
swap $i $min
done
}

###################################################################
##
# Variable Initialization
#
###################################################################
##

echo "Enter Numbers to be Sorted : "

read -a ARRAY

count=${#ARRAY[@]}

###################################################################
##
# Main Script Starts Here
#
###################################################################
##

echo "-------------------------------------------------------------
--"

echo "Numbers Before Sort:"

printnumbers

sortnumbers

echo "Numbers After Sort: "

printnumbers

echo "-------------------------------------------------------------
--"

OUTPUT:

[root@www blog]# sh selectionsort.sh


Enter Numbers to be Sorted :
34 76 -8 12 23 5 9 -2 88 41 62
---------------------------------------------------------------
Numbers Before Sort:
34 76 -8 12 23 5 9 -2 88 41 62
Numbers After Sort:
-8 -2 5 9 12 23 34 41 62 76 88
---------------------------------------------------------------

NOTE: If we complement the if condition in this program, it will


give
out the sorted array in descending order.

Posted by venu k at 9:29 AM 0 comments

Labels: Shell Scripts

Bubble Sort Shell Script

#!/bin/bash
# SCRIPT: bubblesort.sh
# LOGIC:
# Bubble sort is a simple sorting, it works by repeatedly stepping
# through the list to be sorted, comparing two items at a time and
# swapping them if they are in the wrong order. If you are sorting
# the data in Ascending order, at the end of the first pass, the
# "heaviest" element has move to bottom. In the second pass, the
# comparisons are made till the last but one position and now
second
# largest element is placed at the last but one position. And so
# forth.
#
###################################################################
##
# Define Functions Here
#
###################################################################
##

printnumbers()
{
echo ${ARRAY[*]}
#You can also use bellow code
#for ((i=0;i<count;i++))
#do
#echo -n " ${ARRAY[i]} "
#done
}

exchange()
{
temp=${ARRAY[$1]}

ARRAY[$1]=${ARRAY[$2]}

ARRAY[$2]=$temp

sortnumbers()
{
for (( last=count-1;last>0;last--))
do
for((i=0;i<last;i++))
do
j=$((i+1))
if [ ${ARRAY[i]} -gt ${ARRAY[j]} ]
then

exchange $i $j

fi
done
done
}

###################################################################
##
# Variable Initialization
#
###################################################################
##

echo "Enter Numbers to be Sorted"

read -a ARRAY

count=${#ARRAY[@]}

###################################################################
##
# Main Script Starts Here
#
###################################################################
##

echo "-------------------------------------------------------------
-"

echo "Numbers Before Sort:"

printnumbers

echo

sortnumbers

echo "Numbers After Sort: "

printnumbers

echo "-------------------------------------------------------------
-"

OUTPUT:

[root@www blog]# sh bubblesort.sh


Enter Numbers to be Sorted :
78 34 12 98 21 8 36 98 12 88 7 5 61 -12 62 -1 77 -46
------------------------------------------------------
Numbers Before Sort:
78 34 12 98 21 8 36 98 12 88 7 5 61 -12 62 -1 77 -46

Numbers After Sort:


-46 -12 -1 5 7 8 12 12 21 34 36 61 62 77 78 88 98 98
------------------------------------------------------

NOTE: If we complement the if condition in this program, it will


give
out the sorted array in descending order.

Method2: Without Using Arrays

#!/bin/bash
# SCRIPT: bubblesort2.sh
# Without using arrays
#
###################################################################
##
# Define Functions Here
#
###################################################################
##

printnumbers()
{
k=1
while [ $k -le $max ]
do
eval echo -n "\$x$k"
echo -n " "
let k++
done
echo
}

###################################################################
##
# Variable Initialization
#
###################################################################
##

echo -n "Enter Total Numbers to be Sorted : "


read max
count=1
while [ $count -le $max ]
do
echo -n "Enter number $count: "
read x$count
let count++
done

###################################################################
##
# Main Script Starts Here
#
###################################################################
##

echo -e "\nElements Before Sort"


printnumbers

for (( last=count-1;last>0;last--))
do
for ((i=1;i<last;i++))
do
j=$((i+1))
eval sval=\$x$i
eval nval=\$x$j

#The eval command evaluates the command line to complete any shell
#substitutions necessary and then executes the command. So $i and
$j
#substituted first then $x1 and $x2 evaluated.

if [ $sval -gt $nval ]


then
eval x$i=$nval
eval x$j=$sval
fi
done
done

echo "Elements After Sort: "


printnumbers

OUTPUT:

[root@www shell]# sh bubblesort2.sh


Enter Total Numbers to be Sorted : 6
Enter number 1: 12
Enter number 2: -4
Enter number 3: 6
Enter number 4: -11
Enter number 5: 43
Enter number 6: 9

Elements Before Sort


12 -4 6 -11 43 9
Elements After Sort:
-11 -4 6 9 12 43
Posted by venu k at 9:23 AM 0 comments

Labels: Shell Scripts

Tuesday, April 20, 2010


Shell Script to Display Time and Date in the Top Right Corner of the Screen.
Using tput command:

#!/bin/bash
# SCRIPT: digclock.sh
# USAGE: ./digiclock &
# PURPOSE: Displays time and date in the top right corner of the
# screen using tput command.
# To stop this digclock use command "kill pid"
################################################################

####################### VARIABLE DECLARATION ###################

# To place the clock on the appropriate column, subtract the


# length of $Time and $Date, which is 22, from the total number
# of columns

Columns=$(tput cols)
Startpoint=$(($Columns-22))

# If you're in an X Window System terminal,you can resize the


# window, and the clock will adjust its position because it is
# displayed at the last column minus 22 characters.

Color1=`tput setab 2` # Green background color for time


Color2=`tput setab 6` # Cyan background color for date
Normal=`tput sgr0` # back to normal screen colors

####################### MAIN PROGRAM ###########################

# The script is executed inside a while without conditions

while :
do
Time=`date +%r`
Date=`date +"%d-%m-%Y"`
tput sc #Save the cursor position&attributes
tput cup 0 $Startpoint

# You can also use bellow one liner


# tput cup 0 $((`tput cols`-22))
# But it is not efficient to calculate cursor position for each
# iteration. That's why I placed variable assignment before
# beginning of the loop.

# print time and date in the top right corner of the screen.

echo -n $Color1$Time $Color2$Date$Normal

# restore the cursor to whatever was its previous position


tput rc

# Delay for 1 second

sleep 1

done

Using ANSI escape sequences:

The ANSI escape sequences don't work in all terminal emulators,


but
they do fine in xterm. Here's the script:

#!/bin/bash
# SCRIPT: digclock.sh
# USAGE: ./digiclock &
# PURPOSE: Displays time and date in the top right corner of the
# screen using ANSI escape sequences.
# To stop this digclock use command kill pid.
################################################################

#################### VARIABLE DECLARATION ######################

# To place the clock on the appropriate column, subtract the


# length of $Time and $Date, which is 22, from the total number
# of columns

Columns=$(tput cols)
Startpoint=$(($Columns-22))

# If you're in an X Window System terminal,you can resize the


# window, and the clock will adjust its position because it is
# displayed at the last column minus 22 characters.

########################### MAIN PROGRAM #######################

# The script is executed inside a while without conditions.

while :
do
Time=`date +%r`
Date=`date +"%d-%m-%Y"`
echo -en "\033[s" #save current screen position & attributes

tput cup 0 $Startpoint


# You can also use bellow one liner.
# tput cup 0 $((`tput cols`-22))
# But it is not efficient to calculate cursor position for each
# iteration. That's why I placed variable assignment before
# beginning of the loop

# print time and date in the top right corner of the screen

echo -en "\033[42m$Time \033[46m$Date\033[0m"

#restore current screen position & attributes

echo -e -n "\033[u"

#Delay for 1 second

sleep 1
done

Save the script as digclock.sh,change permissions to 755 using


chmod,
and run it with ./digclock.sh & or . digclock.sh & or sh digclock
&.
The time and date should now appear at the top right of your
screen.

Output:

When you run digclock.sh, the terminal will return the job number
and
process identifier (PID) of the digclock.sh process. From above
output
you can find job number is "1" and PID is "15800".

You can end the execution of the script by two ways:

1. Using the kill command and specifying the job number or process
ID.
If you don't remember job number or PID, you can get job number
by
running jobs command and PID by ps command.

$ jobs
[1]+ Running ./digclock.sh &
$ shell]# ps | grep digclock
15800 pts/1 00:00:00 digclock.sh

To kill this job/process, either kill %1 or kill 15800 works.

$ kill %1
$
[1]+ Terminated ./digclock.sh
or
$ kill 15800
$
[1]+ Terminated ./digclock.sh

2. Using the fg command. The fg command switches a job running in


the
background into the foreground, Then press Ctrl+c to terminate
the
job. If no job number is specified, then fg command acts upon
the
currently running job.

$ fg 1
./digclock.sh

Ctrl+c
$

With this script, you can display not only a clock, but other
useful
information as well. For example,monitoring free space with df
command
or CPU's load average with uptime command. Samba, Apache, and many
other servers have status commands where you can extract pieces of
information to show this way.
Posted by venu k at 6:05 AM 0 comments

Labels: Shell Scripts

Saturday, February 27, 2010


Shell Script to Upload a File to the Remote FTP Server

#!/bin/bash
# SCRIPT : upload.sh
# USAGE : ./upload.sh [-d remote directory path] -f "File-to-
upload"
# -d option is optional by default it takes servers home
dir
# or
# ./upload.sh "Filename-to-upload"
#
# PURPOSE : Upload file to remote ftp server.

############### DEFINE FUNCTIONS HERE ##############

Usage()
{
echo " USAGE
"
echo " $0 [-d \"Remote Directory Path\"] -f \"Filename-to-
upload\""
echo "-------------------------- or -----------------------------
"
echo " $0 Filename-to-upload"
exit 1
}

################# ARGUMENTS CHECKING #################

while getopts d:f: choice


do
case $choice in
d) Dname=$OPTARG;;
f) Fname=$OPTARG;;
esac
done

[ $# -eq 1 ] && Fname=$1


[ -z $Dname ] && Dname="/" #change it to suit
[ -z $Fname ] && echo "Bad Arguments" && Usage

[ ! -e $Fname ] && echo "$0: $Fname no such file" && exit 1

############### DEFINE VARIABLES HERE ################

Server="ftp.checksoftware.com" #Remote ftp server.


Username="anonymous" #Remote ftp user name.
Password="venuk@gmail.com" #Remote ftp Password.

# change above to suit

############### MAIN PROGRAM STARTS HERE #############

# Remove comment lines within the here document before run the
script

ftp -n $Server <<ServerEnd


user "$Username" "$Password"
# binary command Set the file transfer type to support binary file
# transfer.So you can transfer all type of files.

binary

# hash command is used for printing hash-sign("#") for each data


block
# transferred. The size of data block is system dependent.In my box
it
# is 1024 bytes. hash command is a toggle switch, by default it is
set
# off most systems.

hash # comment it if you don't need it

cd $Dname

# pwd command prints current directory on the remote host. This


shows
# your file is uploading to which directory.

pwd # comment it if you don't need it

put "$Fname"
bye
ServerEnd

exit 0

OUTPUT:

[root@www ~]# ./upload.sh


Bad Arguments
USAGE
./upload.sh [-d "Remote Directory Path"] -f "Filename-to-upload"
-------------------------- or -----------------------------
./upload.sh Filename-to-upload
[root@www ~]# ./upload.sh -f samplepic.jpg -d /incoming
Hash mark printing on (1024 bytes/hash mark).
257 "/incoming" is current directory.
###############################################
[root@www ~]# ./upload.sh samplepic.jpg
Hash mark printing on (1024 bytes/hash mark).
257 "/" is current directory.
samplepic.jpg: Permission denied
Posted by venu k at 9:27 AM 1 comments
Labels: Shell Scripts

Monday, December 28, 2009


Copy Progress Bar Shell Script V2
This is the upgrade version of the ddcopy_progress.sh script posted on 2nd November.

#!/bin/bash
#
# SCRIPT: ddcopy.sh
# PURPOSE: Copies files and shows the progress of copying.
#
#............................USAGE...........................
# This script copies only files not directories
# ddcopy <Source filename or Path> <Destination filename or Path>
# ddcopy <Source filename or Path> <Destination Directory or Path>

##################################################################
# Arguments Checking #
##################################################################

if [ $# -eq 0 ] # Look for parameters supplied or not


then
echo "$0: missing file operand"
exit 1
fi

if [ $# -eq 1 ] # Look for exactly one parameter


then
echo "$0 : missing destination file operand after '$1'"
exit 1
fi

if [ $# -eq 2 ]
then
Source="$1"
Dest="$2"
if [ ! -e "$1" ] # Check source file exist or not
then
echo "$0: cannot stat '$1': No such file or directory"
exit 1
elif [ -d "$1" ]
then
echo "$0: Source file '$1' is a directory"
exit 1
fi
egrep -q "^\/|\/$" <<<$2

if [ $? -eq 0 -a ! -d $2 ]
then
echo "$0: cannot create regular file '$2' : Is a directory"
exit 1
fi

if [ -d "$2" ]
then
filename=`basename "$1"`
$(egrep -q "\/$" <<<$2) && Dest="$2$filename" ||
Dest="$2/$filename"
fi

if [ -e "$Dest" -a -f "$Dest" ]
then
echo -n "$0: $Dest already exist : overwrite '$Dest' (y/n)?
"
read answer
if [ "$answer" = "n" -o "$answer" = "N" ]
then
exit 1
fi
fi
fi

###################################################################
# DEFINE VARIABLES HERE #
###################################################################

Seek=0 # skip BLOCKS bs-sized blocks at start of


output
Skip=0 # skip BLOCKS bs-sized blocks at start of
input
Bsize=128000 # block size
size=`stat -c %s "$Source"`

# Bellow 25MB files copied directly with copy command


# If you want progress bar for < 25MB files also, remove bellow
# if block

if [ $size -lt 25000000 ]


then
cp "$Source" "$Dest"
exit 0
fi
blocks=$((size/Bsize)) # total blocks of input file

lastblock=$((size%Bsize)) # last block, which size < $Bsize

# If last block size is > 0 then add 1 block to existing blocks.

if [ $lastblock -gt 0 ]
then
let blocks++
fi

# I am dividing screen width 60 as 20 parts.Each part is filled


# with a colour after each iteration.

# Make blocks count dividable by 20.

addblocks=$((blocks%20))
if [ $addblocks -gt 0 ]
then
adjustblocks=$((20-addblocks))
blocks=$((blocks+adjustblocks))
fi

Count=$((blocks/20))

# Count variable contain number of blocks to be copied for


# each iteration

###################################################################
# MAIN PROGRAM STARTS HERE #
###################################################################

printf "\e[40m\e[43m%60s\n\e[A" " "

for ((i=1;i<=20;i++))
do

dd if="$Source" of="$Dest" bs=128kB seek=$Seek skip=$Skip \


count=$Count 2>/dev/null

Skip=$((Skip+$Count))
Seek=$((Seek+$Count))
j=$((j+3)) # 60/20 each part is 3 chars
length

printf "\e[40m\e[7m%${j}s\n\e[A" " "


# echo -e "\033[7m \c"

done
printf "\e[0m\n"
#echo -e "\033[0m"

OUTPUT:
Screen Shot1:

Screen Shot2:

Screen Shot3:

Posted by venu k at 10:46 PM 2 comments

Labels: Shell Scripts

Tuesday, November 17, 2009


Shell Script To Produce Prime Numbers Within A Range

#!/bin/bash
# SCRIPT: primenumbers.sh
# USAGE : ./primenumbers.sh <Range Value>
# or;
# ./ primenumbers.sh <Start Range Value> <End Range Value>
# PURPOSE: Produce prime numbers within a range lmit.

############### DEFINE FUNCTIONS HERE ##############

Usage()
{
echo "********BAD ARGUMENTS**********"
echo "Usage: scriptname <Range Value >"
echo " or "
echo "Usage: scriptname <Start Range Value> <End Range Value>"
exit 1
}
################# ARGUMENTS CHECKING #################

[ $# -gt 2 -o $# -lt 1 ] && Usage


[ $# -eq 1 ] && Bnum=2 && Enum=$1
[ $# -eq 2 ] && Bnum=$1 Enum=$2 && [ $1 -gt $2 ] && Usage
[ $1 -lt 2 ] && Bnum=2

############### MAIN PROGRAM STARTS HERE #############

count=1

while [ $Bnum -le $Enum ]


do
num=$Bnum
Prime="yes"
i=1

#while [ $i -lt $((num/2)) ]


while [ $((i*i)) -lt $((num-1)) ]
do
let i++
if [ $((num%i)) -eq 0 ] # you can also use `expr $num %
$i`
then
Prime="no"
break
fi
done

[ "$Prime" = "yes" ] && printf "%5d " $num && let count++

# count is used to print 10 values in a row

[ $count -eq 11 ] && count=1 && echo


let Bnum++
done
echo

OUTPUT:

$ ./primenumbers.sh 1 350
2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113
127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199 211 223 227 229
233 239 241 251 257 263 269 271 277 281
283 293 307 311 313 317 331 337 347 349

$ ./primenumbers.sh 1900 2500


1901 1907 1913 1931 1933 1949 1951 1973 1979 1987
1993 1997 1999 2003 2011 2017 2027 2029 2039 2053
2063 2069 2081 2083 2087 2089 2099 2111 2113 2129
2131 2137 2141 2143 2153 2161 2179 2203 2207 2213
2221 2237 2239 2243 2251 2267 2269 2273 2281 2287
2293 2297 2309 2311 2333 2339 2341 2347 2351 2357
2371 2377 2381 2383 2389 2393 2399 2411 2417 2423
2437 2441 2447 2459 2467 2473 2477

$ ./primenumbers.sh 200
2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113
127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199

[root@localhost shell]# ./primenumbers.sh 200 100


********BAD ARGUMENTS**********
Usage: scriptname <Range Value>
or
Usage: scriptname <Start Range Value> <End Range Value>

NOTE:
this script can't find the highest prime number,but it can figure out the highest prime number your
system is capable of calculating.

Posted by venu k at 11:58 AM 2 comments

Labels: Shell Scripts

Shell Script to Find Prime Number

NOTE:
Method 1 is a very bad method it takes more and more time for
calculation.
Method 3 and Method 4 have given good results, they have taken less
time.
As per my observation Method 3 is quite a bit faster than the
Method 4.

Method 1:
#!/bin/bash
# SCRIPT: prime1.sh
# USAGE : ./prime1.sh
# PURPOSE: Finds whether given number is prime or not

################################################################

echo enter a number


read num
i=2

while [ $i -lt $num ]


do
if [ `expr $num % $i` -eq 0 ]
then
echo "$num is not a prime number"
echo "Since it is divisible by $i"
exit
fi
i=`expr $i + 1`
done

echo "$num is a prime number "

Method 2:
#!/bin/bash
# SCRIPT: prime2.sh
# USAGE : ./prime2.sh
# PURPOSE: Finds whether a given number is prime or not

#################### DEFINE VARIABLES ####################

echo enter a number


read num

[ $num -lt 2 ] && echo "Sorry 0 and 1 are not prime numbers" &&
exit 1

i=2

#################### MAIN PROGRAM STARTS HERE ############

while [ $i -le `expr $num / 2` ]


do
r=`expr $num % $i`
if [ $r -eq 0 ]
then
break
fi
i=`expr $i + 1`
done

if [ $i -gt `expr $num / 2` ]


then
echo "$num is a prime number"
else
echo "$num is not a prime number"
echo "Since it is divisible by $i"
fi

Method 3:
#!/bin/bash
# SCRIPT: prime3.sh
# USAGE : ./prime3.sh
# PURPOSE: Finds whether a given number is prime or not.

################ ARGUMENTS CHECKING #################

# If you are a beginner leave this arguments checking part


# Go directly to main program part.

if [ $# -ne 1 ]
then
echo "Usage: scriptname "
exit 1
fi

expr $1 + 1 &>/dev/null
if [ $? -ne 0 ]
then
echo "Sorry, You supplied non numerical value"
exit 2
fi

[ $1 -lt 2 ] && echo "Sorry,Values < 2 are not prime numbers" &&
exit 1

############### MAIN PROGRAM STARTS HERE #############

num=$1
i=2

while [ $i -le $((num/2)) ]


do

if [ $((num%i)) -eq 0 ] # you can also use `expr $num %


$i`
then
echo "$num is not a prime number"
echo "Since it is divisible by $i"
exit 0
fi
let i++ # you can also use i=`expr $i +
1`
done

echo "$num is a prime number"

Method 4:
#!/bin/bash
# SCRIPT: prime4.sh
# USAGE : ./prime4.sh
# PURPOSE: Finds whether a given number is prime or not.

################ ARGUMENTS CHECKING #################

# If you are a beginner leave this arguments checking part


# Go directly to main program part.

if [ $# -ne 1 ]
then
echo "Usage: scriptname "
exit 1
fi

expr $1 + 1 &>/dev/null
if [ $? -ne 0 ]
then
echo "Sorry, You supplied non numerical value"
exit 2
fi

[ $1 -lt 2 ] && echo "Sorry,Values < 2 are not prime numbers" &&
exit 1

############### MAIN PROGRAM STARTS HERE #############

num=$1
i=2

while [ $i -le $((num/2)) ]


do

if [ $(((num/i)*i)) -eq $num ]


then
echo "$num is not a prime number"
echo "Since it is divisible by $i"
exit 0
fi
let i++ # you can also use i=`expr $i + 1`

done
echo "$num is a prime number"

OUTPUT1:

$ ./prime1.sh <<< 99991


enter a number
99991 is a prime number

real 3m35.435s
user 0m41.738s
sys 1m53.501s

$ time ./prime2.sh <<< 99991


enter a number
99991 is a prime number

real 2m40.494s
user 0m28.650s
sys 1m19.991s

$ time ./prime3.sh 99991


99991 is a prime number

real 0m3.040s
user 0m2.778s
sys 0m0.232s

$ time ./prime4.sh 99991


99991 is a prime number

real 0m3.150s
user 0m2.898s
sys 0m0.211s

OUTPUT2:

$ time ./prime1.sh <<< 3013


enter a number
3013 is not a prime number
Since it is divisible by 23
real 0m0.059s
user 0m0.011s
sys 0m0.038s

$ time ./prime2.sh <<< 3013


enter a number
3013 is not a prime number
Since it is divisible by 23

real 0m0.077s
user 0m0.014s
sys 0m0.048s

$ time ./prime3.sh 3013


3013 is not a prime number
Since it is divisible by 23

real 0m0.008s
user 0m0.004s
sys 0m0.006s

$ time ./prime4.sh 3013


3013 is not a prime number
Since it is divisible by 23

real 0m0.008s
user 0m0.005s
sys 0m0.002s

Posted by venu k at 8:46 AM 0 comments

Labels: Beginners Scripts, Shell Scripts

Monday, November 2, 2009


Copy Progress Bar Shell Script
This script not replaces cp command. This is a sample script for practice purpose.
I am going to develop more elegant script, which fulfil most of the cp command strengths.
I will post complete version of the script as soon as possible,
I shall really appreciate all comments and suggestions to improve this script.

#!/bin/bash
#
# SCRIPT: ddcopy_progress.sh
# PURPOSE: This script is used to watch progress of copying.
#
# Note: I am using destination file as $$.temp .This is because,
# after testing you can easily delete temp files using
# rm -f *.temp

#############################################
# Arguments Checking #
#############################################

if [ $# -ne 1 ] # Look for exactly one parameter


then
echo "..............Usage Error........."
echo "Usage: $0 Sourcefil"
exit 1
fi

if [ ! -e $1 ] # Check source file exist or not


then
echo "File $1 not exist"
exit 1
fi

#############################################
# DEFINE VARIABLES HERE #
#############################################

Seek=0 # Skip BLOCKS bs-sized blocks at start of output


Skip=0 # Skip BLOCKS bs-sized blocks at start of input
Bsize=128000 # Block size
size=`stat -c %s $1`
blocks=$((size/Bsize)) # Total blocks of input file

lastblock=$((size%Bsize)) # Last block, which size < $Bsize

# If last block size is > 0 then add 1 block to existing blocks.

if [ $lastblock -gt 0 ]
then
let blocks++
fi

# I am dividing screen width 60 as 20 parts.Each part is filled with color


# after each iteration.

# Make blocks count dividable by 20.

addblocks=$((blocks%20))
if [ $addblocks -gt 0 ]
then
adjustblocks=$((20-addblocks))
blocks=$((blocks+adjustblocks))
fi

Count=$((blocks/20))

# Count variable contain number of blocks to be copied for each iteration

###############################################
# MAIN PROGRAM STARTS HERE #
###############################################

printf "\e[40m\e[43m%60s\n\e[A" " "

for ((i=1;i<=20;i++))
do

dd if=$1 of=$$.temp bs=128kB seek=$Seek skip=$Skip count=$Count 2>/dev/null


Skip=$((Skip+$Count))
Seek=$((Seek+$Count))
j=$((j+3)) # 60/20 each part is 3 chars length
printf "\e[40m\e[7m%${j}s\n\e[A" " "
# echo -e "\033[7m \c"
# sleep 1 # Uncomment it for small files

done
printf "\e[0m\n"
#echo -e "\033[0m"

Output:
Screen Shot1:

Screen Shot2:

Screen Shot3:

Screen Shot4:
Observation:
I tested above script with different block count.But I didn't get accurate result.
Some times less count script given good result, some times more block count given
good result.
I copied 1.8 GB Movie file with this script.With time command it has give bellow
result.

real 1m12.646s
user 0m0.043s
sys 0m7.854s

From my observation this script has taken less time compared with mouse copy and
paste method. Copy and paste has taken 1m14.02s averagely.

Posted by venu k at 4:21 AM 2 comments

Labels: Shell Scripts

Tuesday, September 22, 2009


Sample System Monitor Shell Script - Using Options
#!/bin/bash
# sys_monitor2.sh
# Usage: sys_monitor2.sh [-u|-d|-f (D/M)| -c number | -m number]
# Sample system monitor script using options
# Tested under Fedora 9

Invalidoptions()
{
echo "Usage: `basename $0` [OPTIONS]"
echo "OPTIONS:"
echo -e "\t -d for display today's date"
echo -e "\t -u for Logged in users list"
echo -e "\t -f ARG for Disk and Memory Statistics"
echo -e "\t (ARG=D for disk statistics; ARG=M for memory statistics)"
echo -e "\t -c ARG for Top CPU consuming process"
echo -e "\t (ARG=10 means top 10 process)"
echo -e "\t -m ARG for Top Memory consuming process"
echo -e "\t (ARG=10 means top 10 process)"
echo -e "\t Note: Only one option at a time and -f,-c and -m require argument"
exit 1
}

Isnumber()
{
if [ $1 -eq $1 2> /dev/null ]
then
:
else
echo -e "You supplied bad argument, \"$1\" is not a number"
Invalidoptions
fi
}

if [ $# -lt 1 -o $# -gt 2 ]
then
Invalidoptions
fi

if [ $# -eq 1 -a "$1" != "-d" -a "$1" != "-u" -a "$1" != "-f" -a "$1" != "-c" ]


then
Invalidoptions
fi

if [ $# -eq 2 ] && [ "$1" != "-f" -a "$1" != "-c" -a "$1" != "-m" ]


then
Invalidoptions
fi

choice=
top="head -$2"
while getopts udf:c:m: choice
do
case $choice in
d) echo -e " Today's Date: \c"
date +" %d-%h-%Y Time: %T";;
u) echo -e "\tCurrently Logged In Users"
who;;
f)
if [ "$OPTARG" = "D" ]
then
echo -e "\t\tDisk Statistics"
df -h | grep "%"
elif [ "$OPTARG" = "M" ]
then
echo -e "\t Memory Statistics "
free -m | awk 'BEGIN{printf "\t\tTotal\tUsed\tFree\n"; OFS="\t" }\
/Mem/||/Swap/{printf "\t"; print $1,$2,$3,$4}'
else
Invalidoptions
fi;;
m) Isnumber $OPTARG
k3sort="sort -nr -k 3"
echo -e " PID PPID MEM CPU COMMAND "
ps -Ao pid= -o ppid= -o pmem= -o pcpu= -o comm=|$k3sort|$top;;
c) Isnumber $OPTARG
k4sort="sort -nr -k 4"
echo -e " PID PPID MEM CPU COMMAND "
ps -Ao pid= -o ppid= -o pmem= -o pcpu= -o comm=|$k4sort|$top;;

esac
done
Output:

[root@localhost blog]# sh sys_monitor2.sh -u


Currently Logged In Users
root tty7 2009-09-23 13:48 (:0)
root pts/2 2009-09-23 14:36 (:0.0)

[root@localhost blog]# sh sys_monitor2.sh -d


Todays Date: 23-Sep-2009 Time: 16:50:38

[root@localhost blog]# sh sys_monitor2.sh -m 5


PID PPID MEM CPU COMMAND
3122 3102 9.6 3.0 firefox
2765 2540 1.9 0.0 nautilus
3849 1 1.7 1.0 ktorrent
2882 1 1.6 0.0 tomboy
2810 1 1.6 0.0 /usr/bin/sealer

[root@localhost blog]# sh sys_monitor2.sh -m


Usage: sys_monitor2.sh [OPTIONS]
OPTIONS:
-d for display today's date
-u for Logged in users list
-f ARG for Disk and Memory Statistics
(ARG=D for disk statistics; ARG=M for memory statistics)
-c ARG for Top CPU consuming process
(ARG=10 means top 10 process)
-m ARG for Top Memory consuming process
(ARG=10 means top 10 process)
Note: Only one option at a time and -f,-c and -m require argument
Posted by venu k at 10:22 PM 0 comments

Labels: Shell Scripts

Sample System Monitor Shell Script -Menu Based

#!/bin/bash
# sys_monitor.sh
# Sample system monitor script using menu
# Tested under Fedora 9
#
# Create the following menu and clear the screen each time it appears
#

clear
echo -e "\033[1m `uname -or` Monitor script\033[0m"
items=" 1.Date
2.Current Users
3.Disk Statistics
4.Memory Statistics
5.Top 10 Memory consuming process
6.Top 10 CPU consuming process
7.Exit"

exit_function()
{
clear
exit
}

#function enter is used to go back to menu and clear screen

enter()
{
ans=
echo ""
echo -e "Do you want to continue(y/n):\c"
stty -icanon min 0 time 0
# When -icanon is set then one character has been received.
# min 0 means that read should read 0 characters.
# time 0 ensures that read is terminated the moment one character is hit.

while [ -z "$ans" ]
do
read ans
done
#The while loop ensures that so long as at least one character is not received
# "read" continue to get executed

if [ "$ans" = "y" -o "$ans" = "Y" ]


then
stty sane # Restoring terminal settings
clear
else
stty sane
exit_function
fi
}

choice=
h10="head -10"
while true
do
echo -e "\n\t PROGRAM MENU \n"
echo -e "$items \n"
echo -n "Enter your choice :"
read choice
case $choice in
1) clear; echo -e "\n\n\t\t Today's Date \n"
date +" %d-%h-%Y Time %T"; enter;;
2) clear; echo -e "\n\n\t\t Currently Logged In Users\n"
who; enter;;
3) clear; echo -e "\n\n\t\t Disk Statistics\n"
df -h | grep "%"
enter;;
4) clear; echo -e "\n\n\t\t Memory Statistics\n "
free -m | awk 'BEGIN{printf "\t\tTotal\tUsed\tFree\n\n"; OFS="\t" }\
/Mem/||/Swap/{printf "\t"; print $1,$2,$3,$4}'
enter;;
5) clear
k3sort="sort -nr -k 3"
echo -e "\033[1m PID PPID MEM CPU COMMAND \033[0m "
ps -Ao pid= -o ppid= -o pmem= -o pcpu= -o comm=|$k3sort|$h10
enter;;
6) clear
k4sort="sort -nr -k 4"
echo -e "\033[1m PID PPID MEM CPU COMMAND \033[0m"
ps -Ao pid= -o ppid= -o pmem= -o pcpu= -o comm=|$k4sort|$h10
enter;;
7)exit_function ;;
*)echo -e "You entered wrong option \n Please enter 1,2,3,4,5,6 or 7\n"
echo " Press enter to continue"
read
clear
esac
done

Output:

2.6.25-14.fc9.i686 GNU/Linux Monitor script


PROGRAM MENU

1.Date
2.Current Users
3.Disk Statistics
4.Memory Statistics
5.Top 10 memory cosuming process
6.Top 10 CPU consuming process
7.Exit

Enter your choice :5


PID PPID MEM CPU COMMAND
3122 3102 9.2 2.6 firefox
2765 2540 1.9 0.0 nautilus
3849 1 1.7 1.0 ktorrent
2882 1 1.6 0.0 tomboy
2810 1 1.6 0.0 /usr/bin/sealer
4041 1 1.4 0.1 gnome-terminal
2394 2393 1.4 1.8 Xorg
2759 2540 1.2 0.0 gnome-panel
2876 1 0.9 0.0 clock-applet
2870 1 0.9 0.0 mixer_applet2

Do you want to continue(y/n):


Posted by venu k at 9:31 PM 6 comments

Labels: Shell Scripts


Saturday, September 19, 2009
Bash Script to check after every one minute whether a user has logged in or not

#!/bin/bash
# isuserloggedin.sh
# Usage: isuserloggedin.sh username
# Shell script which checks after every one minute whether a user has logged in
# or not
# You can also run script in background using & then foreground it to view result

if [ $# -ne 1 ]
then
echo "You supplied wrong arguments"
echo "usage : `basename $0` username"
exit 1
fi

isuserexist()
{
grep -w "$1" /etc/passwd > /dev/null

if [ $? -eq 1 ]
then
echo "$1 is not a valid user"
exit 1
fi
}

isuserexist $1
time=0
while true
do
# you can replace following two statements with
# if `who|grep $1 > /dev/null`
who|grep $1 > /dev/null
if [ $? -eq 0 ]
then
echo "User $1 is logged in "
if [ $time -gt 60 ]
then
hours=$((time/60))
minutes=$((time%60))
echo "He is logged in $hours hour(s) $minutes minute(s) late"
else
echo "He is logged in $time minute(s) late"
fi
exit 0

else
let time++
# You can use following formats also
# time=`expr $time + 1 `
# time=$((time+1))

sleep 60
fi
done

Output:
[root@localhost shell]# sh isuserloggedin.sh
you have suplied wrong arguments
usage : isuserloggedin.sh username
[root@localhost shell]# sh isuserloggedin.sh root
User root is logged in
He is logged in 0 minute(s) late
[root@localhost shell]# sh isuserloggedin.sh roott
roott is not a valid user
Run script in background
[root@localhost shell]# sh isuserloggedin.sh venu &
[1] 15917
[root@localhost shell]# User venu is logged in
He is logged in 3 minute(s) late

[1]+ Done sh isuserloggedin.sh venu


Run script in background then foreground it
[root@localhost shell]# sh isuserloggedin.sh venu &
[1] 16223
[root@localhost shell]# fg
sh isuserloggedin.sh venu
User venu is logged in
He is logged in 1 minute(s) late
[root@localhost shell]#

Posted by venu k at 10:33 AM 0 comments

Labels: Shell Scripts

Bash Script to Check whether a user has an account in your system


#!/bin/bash
# validuser.sh
# Usage: validuser.sh username
# Script to check whether suplied user has an account in your system

if [ $# -ne 1 ]
then
echo "You supplied wrong arguments"
echo "Usage : `basename $0` user_name"
exit 1
fi

#grep -w "$1" /etc/passwd > /dev/null


grep -w "^$1" /etc/passwd > /dev/null
if [ $? -eq 1 ]
then
echo "$1 is not a valid user"
else
echo "$1 is a valid user"
fi

# Using greps -q option you can simplify and faster your script
# if `grep -qw "^$1" /etc/passwd`
# greps -q option prints nothing just returns exit status 0 or 1

Out Put:
[root@localhost shell]# sh validuser.sh
You supplied wrong arguments
usage : validuser.sh user_name
[root@localhost shell]# sh validuser.sh venu
venu is a valid user
[root@localhost shell]# sh validuser.sh venuk
venuk is not a valid user
[root@localhost shell]# sh validuser.sh root
root is a valid user
[root@localhost shell]# sh validuser.sh roott
roott is not a valid user
[root@localhost shell]#

Posted by venu k at 10:11 AM 7 comments

Labels: Shell Scripts

Wednesday, September 2, 2009


How to prompt user to enter input within the time limit in a shell script
There are various ways to read input within the time limit in shell script. I am posting 4 methods
here.First three are direct methods. Final one implemented with some logic, just for practice only.

Method 1:
#!/bin/bash
# timedinput1.sh: prompts times out at five seconds.
# Using read command

timelimit=5
echo -e " You have $timelimit seconds\n Enter your name quickly: \c"
name=""
read -t $timelimit name
#read -t $timelimit name <&1
# for bash versions bellow 3.x
if [ ! -z "$name" ]
then
echo -e "\n Your name is $name"
else
echo -e "\n TIME OUT\n You failed to enter your name"
fi
Output:
[root@localhost shell]# sh timedinput1.sh
You have 5 seconds
Enter your name quickly: king

Your name is king


[root@localhost shell]# sh timedinput1.sh
You have 5 seconds
Enter your name quickly:
TIME OUT
You failed to enter your name

Method 2:
#!/bin/bash
# timedinput2.sh
# Using stty command

timelimit=5
# Time limit to enter input
echo -e " You have only $timelimit seconds\n Enter your name quickly: \c"
name=""
stty -icanon min 0 time ${timelimit}0

# "min N" with -icanon, set N characters minimum for a completed read
# "time N" with -icanon, set read timeout of N tenths of a second (i.e. 50 means 5
seconds )

read name
if [ ! -z "$name" ]
then
echo " Your name is $name"
else
echo -e "\n TIME OUT\n You failed to enter your name"
fi
stty sane
#restore terminal settings
Output:
[root@localhost shell]# sh timedinput2.sh
You have only 5 seconds
Enter your name quickly: Sachin Ramesh Tendulkar
Your name is "Sachin Ramesh Tendulkar"
[root@localhost shell]# sh timedinput2.sh
You have only 5 seconds
Enter your name quickly:
TIME OUT
You failed to enter your name
Observation:
There is difference between method1 and method2.In method1 you should to enter input within 5
seconds.But in method 2 you have 5 seconds after a character has been hit.This is because time n means
wait till n seconds after a character has been hit.So in method2 you can give any length of input.

Method3:
#!/bin/bash
# timedinput3.sh
# using TMOUT environment variable

TMOUT=5
# TMOUT is an Internal Variable
# If the $TMOUT environment variable is set to a non zero value time, then the shell prompt will time
out after $time seconds.This will cause a logout.
# If you run this script in current shell after 5 seconds you will be logout

echo -e " You only have $TMOUT seconds\n Enter your name quickly: \c"
name=""
read name
if [ ! -z "$name" ]
then
echo " Your name is $name"
else
echo -e "\n TIME OUT\n You failed to enter your name"
fi
Output:
[root@localhost shell]# sh timedinput3.sh
You only have 5 seconds
Enter your name quickly: Ricky ponting
Your name is "Ricky ponting"
[root@localhost shell]# sh timedinput3.sh
You only have 5 seconds
Enter your name quickly:
TIME OUT
You failed to enter your name

Method4:
#!/bin/bash
# timedinput4.sh
# Using sleep command

timelimit=5
#set another value if you require

trap 'echo -e "\n TIMEOUT"; exit 14' 14


# Trapping signal 14

echo -e " You only have $timelimit seconds \n What is your name:\c"

sleep $timelimit && kill -s 14 $$ &

# Waits 5 seconds, then sends sigalarm to script($$ environment variable gives pid of current script).
read name
echo " Your name is \"$name\""
kill $!
#kills back ground job (i.e. sleep command)
exit
Output:
[root@localhost shell]# sh timedinput4.sh
You only have 5 seconds
What is your name:Ganguly
Your name is "Ganguly"
[root@localhost shell]# sh timedinput4.sh
You only have 5 seconds
What is your name:Kapil Dev
Your name is "Kapil Dev"
timedinput4.sh: line 16: 3814 Terminated sleep $timelimit && kill -s 14 $$
[root@localhost shell]# sh timedinput4.sh
You only have 5 seconds
What is your name:
TIMEOUT

Posted by venu k at 1:25 PM 1 comments

Labels: Shell Scripts

Friday, August 14, 2009


GCD of more than two numbers
#!/bin/bash
#************************************************************************************
**********
# gcd.sh: greatest common divisor uses Eclidean algorithm
# Usage : gcd.sh num1 num2 num3 .... (any number of arguments)
# The algorithm used to calculate the GCD two integers is known as the Euclidean algorithm.
# Based on Euclidean algorithm this script is written(Recursive method).
# For checking supplied arguments are integers or not check GCD of two numbers code
#************************************************************************************
***********

# Argument check
# Minimum 2 arguments you should to supply
ARGS=2
BADARGS=65

if [ $# -lt "$ARGS" ]
then
echo
echo "Invalid Arguments"
echo "Usage: $0 first-number second-number"
echo
exit $BADARGS
fi
# Preserve command line argument for future use
cmdargs=$*

function Euclidean()
{
if [ $2 -eq 0 ]
then
return $1
else
Euclidean $2 $(($1%$2)) # calling function recursively
fi
}
Euclidean $1 $2
return=$?
# $? returns the exit status of script. This is one method to capture return value of a function

shift
# Shifts command line arguments one step.Now $1 holds second argument

while true
do
shift
# shift is used to pick up next command line argument to continue iteration
# $# holds total number of arguments.At every shift operation its value decreases one

if [ $# -eq 0 ]
then
break 2
fi
Euclidean $return $1
return=$?
done
echo "GCD of $cmdargs is $return"
exit 0

Posted by venu k at 11:43 PM 0 comments

Labels: Shell Scripts


Thursday, August 13, 2009
GCD of two nubers
I written three different methods to calculate GCD of two numbers

Method 1:
#!/bin/bash
#************************************************************************************
*******
# gcd.sh: greatest common divisor uses Eclidean algorithm
# Usage : gcd.sh number1 number2
# The algorithm used to calculate the GCD between two integers is known as the Euclidean
# algorithm(Recursive method).
#************************************************************************************
*******

#----------------------------------------------------------------------
# Argument check
ARGS=2
BADARGS=65

if [ $# -ne "$ARGS" ]
then
echo ; echo "Invalid Arguments"
echo "Usage: $0 first-number second-number" ; echo
exit $BADARGS
fi

# Check supplied arguments are integers are not

isnumber()
{
if [ $1 -eq $1 2> /dev/null ]
then
:
# : is a null command.This is the shell equivalent of a "NOP"(do nothing)
else
echo -e "\nYou supplied one bad argument \"$1\" is not a number"
echo -e "Usage: $0 first-number second-number\n"
exit $BADARGS
fi
}
isnumber $1
isnumber $2

# ---------------------------------------------------------------------

function Euclidean()
{
if [ $2 -eq 0 ]
then

return $1

else

Euclidean $2 $(($1%$2))
# calling function recursively
fi
}

Euclidean $1 $2

echo "gcd of $1 and $2 is $?"

# $? returns the exit status of script. This is one method to capture return value of a function

exit 0

Method 2:
#!/bin/bash
# gcd2.sh
# Usage: gcd2.sh number1 number2
# For argument check see method 1

gcd ()
{
dividend=$1
divisor=$2
# Arbitrary assignment.
#! It doesn't matter which of the two is larger.

remainder=1

# If uninitialized variable used in loop,it results in an error message


# on the first pass through loop.

if [ $divisor -eq 0 ]
then
echo "GCD of $dividend and $divisor = $dividend"
exit 0
fi

until [ "$remainder" -eq 0 ]


do
let "remainder = $dividend % $divisor"

# Now repeat with 2 smallest numbers

dividend=$divisor .
divisor=$remainder
done
}
# Last $dividend is the gcd.

gcd $1 $2

echo; echo "GCD of $1 and $2 = $dividend"; echo


exit 0

Method 3:
#!/bin/bash
# gcd3.sh
# Usage: gcd3.sh
# This script doesn't use command line arguments.You should to enter two numbers when asking

echo enter two numbers


read n1 n2
remainder=1
# Preserve numbers for future use
t1=$n1
t2=$n2
if [ $n2 -eq 0 ]
then
echo "GCD of $n1 and $n2 = $n1"
exit 0
fi
while [ $remainder -ne 0 ]
do
remainder=`expr $n1 % $n2`
# or use
#remainder=$((n1%n2))
n1=$n2
n2=$remainder
done
echo "GCD of $t1 , $t2 is $n1"

Posted by venu k at 10:35 AM 0 comments

Labels: Shell Scripts

Monday, August 10, 2009


Terminal Lock Program
#************************************************************************************
#Locking a terminal using a shell script.
#This script locks your terminal until you enter correct password (open2world)
#It also traps signals and interrupts
#You can't terminate the script by Ctrl+c or Ctrl+\ or Ctrl+z and Ctrl+d
#************************************************************************************

clear
trap "" 1 2 3 20
lines=`tput lines`
b=`expr $lines / 2 - 4 `

## center function

center()
{
columns=`tput cols`
until [ -z "$1" ]
do
for ((i=1;i<$(((columns-${#1})/2));i++)) do echo -n " " done echo -e "\033[1m \033[5m \033[42m $1
\033[0m " shift done } ## End of center function while true do clear tput cup $b 0
center " TERMINAL LOCKED "
center "Press any key to unlock"
read key
echo -n "enter password : "
read -s password
while true
do
if [ $password = "open2world" ]
then
clear
break 2
# breaks second outer loop
else
echo -e "\n You are an illegal user "
echo -e "\n Enter any key"
read
break
fi
done
done

Analysis :
The trap command allows you to execute a command when a signal is received by your script. It works
like this:

trap arg signals

"signals" is a list of signals to interrupt and "arg" is a command to execute when one of the signals is
received. If "arg" is not supplied script doesn't do any thing after receiving signal.

Note: Two signals "SIGKILL" "SIGSTOP" are unable to trap

Ex: trap "echo signal received" 1 2 3 15


(or use SIGHUP SIGINT SIGQUIT SIGTERM instead of 1 2 3 15 )
What is signal:

A signal is a message which can be sent to a running process. Some times called
software interrupts.

Some of signals and its value:

Signal Value Action Comment


------------------------------------------------------------------------
-
SIGHUP 1 Term Hangup detected on
controlling terminal
or death of controlling
process
SIGINT (Ctrl+c) 2 Term Interrupt from keyboard
SIGQUIT (Ctrl+\) 3 Core Quit from keyboard
SIGTERM 15 Term Termination signal
SIGTSTP (Ctrl+z) 20 Stop Stop typed at tty

Note: There are different standards(POSIX,SUSv) to determine signals and its values.
I tested Above signals in Fedora 9, Other systems may support them or not depending on system
standard(I think almost all standards supports above signals and values).

More stuff:

I used "tput cols" and "tput lines" commands to collect number of columns and lines.
You can also directly use bash variables $LINES ,$COLUMNS to get columns and lines.But
you should to run your script in current shell only. If you run your script in sub shell
current shell will not export $LINES and $COLUMNS variable values.

Posted by venu k at 8:57 AM 0 comments

Labels: Shell Scripts

Friday, June 6, 2008


Backup files to tarred and zip file
#!bin/bash

# backs up all files in current directory modified within last 24 hours


# in a tarred and zipped file
# Replace 1 with how many day's you want to back up files

BACKUPFILE=backup-`date +"%m-%d-%Y"`
# Embeds date in backup filename
archive=${1:-$BACKUPFILE}
#If no filename specified default to backup-MM-DD-YYYY

find . -mtime -1 -type f -print0 xargs -0 tar rvf "$archive.tar"

#check bellow command


# tar cvf - $(find . -mtime -1 -type f -print) > $archive.tar
# It works But will fail to backup file names contain space
# if there is no files containing spaces it is good

# ALSO USE bellow code but it is slow and not portable


# find . -mtime -1 -type f -exec tar rvf "$archive.tar" {} \;
# use rvf option instead of cvf otherwise only one file will be archived

gzip $archive.tar && echo "Directory $pwd backed up in \"$archive.tar.gz\" File"

Posted by venu k at 7:56 AM 1 comments

Labels: Shell Scripts

Wednesday, June 4, 2008


Traversing directory using depth first search
#!/bin/bash
# Traverse a directory using depth first traversal technique
# Usage $0 directorypath
# otherwise it takes current working directory as directory path

depth()
{
#Do a small depth checking how deep into the tree we are
k=0
while [ $k -lt $1 ]
do
echo -n " "
let k++
#or use k=`expr $k + 1`
done
}

traverse()
{
# Traverse a directory

ls "$1"while read i
do
depth $2
if [ -d "$1/$i" ]
then
echo Directory: $1/$i

traverse "$1/$i" `expr $2 + 1`


# Calling this as a subshell means that when the called
# function changes directory, it will not affect our
# current working directory
# If you call this in current shell it gives the error
# bash: traverse: No such file or directory after changing
# the current directory
else

echo File: $1/$i


fi
done
}

# $1 is directory path

if [ -z "$1" ]
then
# Here we are giving '0' is the current depth of direcory
traverse . 0
else
traverse $1 0
fi

Posted by venu k at 6:11 AM 0 comments

Labels: Shell Scripts

Newer Posts Older Posts Home

Subscribe to: Posts (Atom)


Blog Archive

 ▼ 2010 (12)
o ▼ July (4)
 Shell Script to Check Whether a String is Palindro...
 Insertion Sort Shell Script
 Selection Sort Shell Script
 Bubble Sort Shell Script
o ► May (1)
 How to Read a File Line by Line in a Shell Script
o ► April (2)
 Shell Script to Display Time and Date in the Top ...
 How to Handle Cursor Movement in a Shell Script
o ► March (3)
 Creating a User Group and Shared Directory
 UNIX/Linux Advanced File Permissions - SUID,SGID a...
 Linux File and Directory Permissions
o ► February (1)
 Shell Script to Upload a File to the Remote FTP Se...
o ► January (1)
 Shell Colors: colorizing shell scripts

 ► 2009 (24)
o ► December (1)
 Copy Progress Bar Shell Script V2
o ► November (7)
 Linux Baby Rocker
 Shell Script To Produce Prime Numbers Within A Ran...
 Shell Script to Find Prime Number
 How to Pass Arguments to Shell Script
 Shell Script to Check Whether Given Year is a Leap...
 Copy Progress Bar Shell Script
 Shell Script to Create a File with Specified Numbe...
o ► October (7)
 Shell Script to Find Factorial of a Number
 For Loop Example-2
 How to Execute a Shell Script
 Bash for loop example-1
 Bash for Loop Syntax
 Shell Script To Print Pyramid - Using while Loop
 Shell Script To Print Pyramid-Using for Loop
o ► September (5)
 Sample System Monitor Shell Script - Using Options...
 Sample System Monitor Shell Script -Menu Based
 Bash Script to check after every one minute whethe...
 Bash Script to Check whether a user has an account...
 How to prompt user to enter input within the time ...
o ► August (4)
 What is the difference between Hard Link and Soft ...
 GCD of more than two numbers
 GCD of two nubers
 Terminal Lock Program

 ► 2008 (9)
o ► June (4)
 Bash variables scope
 Bash variables type
 Backup files to tarred and zip file
 Traversing directory using depth first search
o ► April (4)
 MENU DRIVEN PROGRAM USING DIALOG UTILITY
 Displaying chess board on the screen
 How can get nth line from a file
 When not to use shell scripts
o ► March (1)
 Why shell(bash) programming

Labels

 Article (13)
 Beginners Scripts (8)
 Linux Fun (1)
 Shell Scripts (22)

Counter

Followers

Popular Posts

 How to Pass Arguments to Shell Script


 How to Read a File Line by Line in a Shell Script


Shell Colors: colorizing shell scripts

 UNIX/Linux Advanced File Permissions - SUID,SGID and Sticky Bit


 Shell Script to Find Prime Number

NOTE:
Method 1 is a very bad method it takes more and more time for
calculation.
Method 3 and Method 4 have given good results, they have taken less
time.
As per my observation Method 3 is quite a bit faster than the
Method 4.

Method 1:
#!/bin/bash
# SCRIPT: prime1.sh
# USAGE : ./prime1.sh
# PURPOSE: Finds whether given number is prime or not

################################################################

echo enter a number


read num
i=2

while [ $i -lt $num ]


do
if [ `expr $num % $i` -eq 0 ]
then
echo "$num is not a prime number"
echo "Since it is divisible by $i"
exit
fi
i=`expr $i + 1`
done

echo "$num is a prime number "

Method 2:
#!/bin/bash
# SCRIPT: prime2.sh
# USAGE : ./prime2.sh
# PURPOSE: Finds whether a given number is prime or not

#################### DEFINE VARIABLES ####################

echo enter a number


read num

[ $num -lt 2 ] && echo "Sorry 0 and 1 are not prime numbers" &&
exit 1

i=2

#################### MAIN PROGRAM STARTS HERE ############

while [ $i -le `expr $num / 2` ]


do
r=`expr $num % $i`
if [ $r -eq 0 ]
then
break
fi
i=`expr $i + 1`
done

if [ $i -gt `expr $num / 2` ]


then
echo "$num is a prime number"
else
echo "$num is not a prime number"
echo "Since it is divisible by $i"
fi

Method 3:
#!/bin/bash
# SCRIPT: prime3.sh
# USAGE : ./prime3.sh
# PURPOSE: Finds whether a given number is prime or not.
################ ARGUMENTS CHECKING #################

# If you are a beginner leave this arguments checking part


# Go directly to main program part.

if [ $# -ne 1 ]
then
echo "Usage: scriptname "
exit 1
fi

expr $1 + 1 &>/dev/null
if [ $? -ne 0 ]
then
echo "Sorry, You supplied non numerical value"
exit 2
fi

[ $1 -lt 2 ] && echo "Sorry,Values < 2 are not prime numbers" &&
exit 1

############### MAIN PROGRAM STARTS HERE #############

num=$1
i=2

while [ $i -le $((num/2)) ]


do

if [ $((num%i)) -eq 0 ] # you can also use `expr $num %


$i`
then
echo "$num is not a prime number"
echo "Since it is divisible by $i"
exit 0
fi
let i++ # you can also use i=`expr $i +
1`

done

echo "$num is a prime number"

Method 4:
#!/bin/bash
# SCRIPT: prime4.sh
# USAGE : ./prime4.sh
# PURPOSE: Finds whether a given number is prime or not.
################ ARGUMENTS CHECKING #################

# If you are a beginner leave this arguments checking part


# Go directly to main program part.

if [ $# -ne 1 ]
then
echo "Usage: scriptname "
exit 1
fi

expr $1 + 1 &>/dev/null
if [ $? -ne 0 ]
then
echo "Sorry, You supplied non numerical value"
exit 2
fi

[ $1 -lt 2 ] && echo "Sorry,Values < 2 are not prime numbers" &&
exit 1

############### MAIN PROGRAM STARTS HERE #############

num=$1
i=2

while [ $i -le $((num/2)) ]


do

if [ $(((num/i)*i)) -eq $num ]


then
echo "$num is not a prime number"
echo "Since it is divisible by $i"
exit 0
fi
let i++ # you can also use i=`expr $i + 1`

done
echo "$num is a prime number"

OUTPUT1:

$ ./prime1.sh <<< 99991


enter a number
99991 is a prime number
real 3m35.435s
user 0m41.738s
sys 1m53.501s

$ time ./prime2.sh <<< 99991


enter a number
99991 is a prime number

real 2m40.494s
user 0m28.650s
sys 1m19.991s

$ time ./prime3.sh 99991


99991 is a prime number

real 0m3.040s
user 0m2.778s
sys 0m0.232s

$ time ./prime4.sh 99991


99991 is a prime number

real 0m3.150s
user 0m2.898s
sys 0m0.211s

OUTPUT2:

$ time ./prime1.sh <<< 3013


enter a number
3013 is not a prime number
Since it is divisible by 23

real 0m0.059s
user 0m0.011s
sys 0m0.038s

$ time ./prime2.sh <<< 3013


enter a number
3013 is not a prime number
Since it is divisible by 23
real 0m0.077s
user 0m0.014s
sys 0m0.048s

$ time ./prime3.sh 3013


3013 is not a prime number
Since it is divisible by 23

real 0m0.008s
user 0m0.004s
sys 0m0.006s

$ time ./prime4.sh 3013


3013 is not a prime number
Since it is divisible by 23

real 0m0.008s
user 0m0.005s
sys 0m0.002s

Posted by venu k at 8:46 AM 0 comments

Labels: Beginners Scripts, Shell Scripts

Thursday, November 12, 2009


Shell Script to Check Whether Given Year is a Leap Year or Not?

Method 1:
#!/bin/bash
#
# SCRIPT : leapyear.sh
# PURPOSE: Checks whether given year is a leap year or not
# USAGE : sh leapyear.sh
# If Year value not supplied, it takes current year as default
#
# This script based on, One year has the length of 365 days, 5 hours,
# 48 minutes and 47 seconds. Because this is rather non-functional,
# a normal year has been given 365 days and a leap year 366 days.

#####################################################
############### DEFINE FUNCTIONS HERE ####################
#####################################################
Leap()
{
# This function tells you if the argument is a leap year or not...

YEAR=$1
NO_OF_DAYS=$(cal $YEAR |egrep "^[ 0-9][0-9]| [ 0-9][0-9]$" |wc -w)

# A single parameter to cal specifies the year (1 - 9999) to be displayed;


# note the year must be fully specified: “cal 89” will not display a
calendar
# for 1989.

# Use egrep or grep -E both are same

# cal command pipes total months and dates to egrep, egrep remove all
lines
# not starting with number or ending with number, then pipes remaining
lines
# to wc command. wc command counts total number of words(days).

if [[ $NO_OF_DAYS -eq 365 ]]


then
echo "$YEAR Is Not A Leap Year "
else
echo "$YEAR Is A Leap Year"
fi

#####################################################
############### MAIN PROGRAM STARTS HERE #################
#####################################################

Year=${1:-$(date +%Y)}
if [ $Year -lt 1 -o $Year -gt 9999 ]
then
echo "Illegal Year Value: Use 1-9999"
exit 1
fi

Leap $Year

Method 2:
#!/bin/bash
#
# SCRIPT : leapyear.sh
# PURPOSE: Checks whether given year is a leap year or not
# USAGE : sh leapyear.sh
# If Year value not supplied, it takes current year as default
#
# This script based on,A leap year comes every 4 years,
# but not every 100 years, then again every 400 years.

#####################################################
############### ARGUMENTS CHECKING #####################
#####################################################

YEAR=${1:-`date +%Y`}

if [ $YEAR -lt 1 -o $YEAR -gt 9999 ]


then
echo "Illegal Year Value: Use 1-9999"
exit 1
fi

#####################################################
############### DECLARE VARIABLES HERE ###################
#####################################################

rem1=$((YEAR%4))
rem2=$((YEAR%100))
rem3=$((YEAR%400))

#####################################################
############## MAIN PROGRAM STARTS HERE ##################
#####################################################

if [ ${rem3} = "0" ]
then
echo "$YEAR Is A Leap Year"
exit
fi

if [ ${rem2} = "0" -a ${rem3} != "0" ]


then
echo "$YEAR Is Not A Leap Year"
exit
fi

if [ ${rem1} = "0" -a ${rem2} != "0" ]


then
echo "$YEAR Is A Leap Year"
else
echo "$YEAR Is Not A Leap Year"
fi

OUTPUT:

[root@localhost shell]# ./leapyear.sh


2009 Is Not A Leap Year
[root@localhost shell]# ./leapyear.sh 2100
2100 Is Not A Leap Year
[root@localhost shell]# ./leapyear.sh 2104
2104 Is A Leap Year
[root@localhost shell]# ./leapyear.sh 21000
Illegal Year Value: Use 1-9999
[root@localhost shell]# ./leapyear.sh 1996
1996 Is A Leap Year

Posted by venu k at 1:17 AM 1 comments

Labels: Beginners Scripts

Sunday, November 1, 2009


Shell Script to Create a File with Specified Number of Lines

#!/bin/bash
#
# SCRIPT: bigfile.sh
# PURPOSE: This script is used to create a text file that
# has a specified number of lines that is specified
# on the command line.
#

usage()
{
echo "............USAGE ERROR............"
echo "USAGE: $0 <number_of_lines_to_create>"
}

# Argument Checking

if [ $# -ne 1 ] # Looking for exactly one parameter


then
usage # Usage error was made
exit 1 # Exit on a usage error
fi

# Define files and variables here

LINE_LENGTH=80 # Number of characters per line


OUT_FILE=bigfile.$$ # New file to create
>$OUT_FILE # Initialize to a zero-sized file
TOTAL_LINES=$1 # Total number of lines to create
LINE_COUNT=0 # Character counter
CHAR=X # Character to write to the file

# Beginning of Main
while ((LINE_COUNT < TOTAL_LINES))
do
CHAR_COUNT=0 # Initialize the CHAR_COUNT to zero on every new line

while ((CHAR_COUNT < LINE_LENGTH)) # Each line is fixed length


do
echo -e "$CHAR\c" >> $OUT_FILE # Echo a single character
let CHAR_COUNT++ # Increment the character counter
done

let LINE_COUNT++
echo>>$OUT_FILE # Give a newline character
done
Posted by venu k at 11:56 AM 0 comments

Labels: Beginners Scripts

Tuesday, October 27, 2009


Shell Script to Find Factorial of a Number

Method 1:
#!/bin/bash
# fact1
# Finding factorial of a given number
#

echo "Enter a number"


read num
fact=1
n=$num
while [ $num -ge 1 ]
do

fact=`echo $fact \* $num|bc`

# You can use bellow commands also


# fact=$((fact*num))
# fact=`expr $fact \* $num`
# But maximum integer value that bash can handle is
# 9223372036854775807.
# An operation that takes a variable outside these
# limits will give an erroneous result. To solve this
# problem store numbers as strings and use bc for math.
let num--

done
echo "factorial of $n is $fact"

Method 2:
#!/bin/bash
# fact2
# Usage : sh fact2 Number

factorial ()
{
local number=$1
if [ $number -eq 0 ]
then
Factorial=1
else
let "next = number - 1"
factorial $next
Factorial=`echo $number \* $Factorial | bc`
# let "Factorial = $number * $Factorial"
fi
return $Factorial 2>/dev/null
}

# Bash function returns integer value only.


# But maximum integer value that bash can handle is
# 9223372036854775807.
# An operation that takes a variable outside these limits
# will give an erroneous result. That's why I redirected
# stderror output to /dev/null

# Main program starts here.


if [ $# -ne 1 ]
then
echo "Invalid Arguments"
echo "Usage: ./fact2.sh Number "
exit 1
fi
factorial $1
echo "Factorial of $1 is $Factorial"

Output:
[root@localhost shell]# ./fact1
Enter a number
8
factorial of 8 is 40320
[root@localhost shell]# ./fact1
Enter a number
23
factorial of 23 is 25852016738884976640000

[root@localhost shell]# ./fact2


Invalid Arguments
Usage: ./fact2.sh Number
[root@localhost shell]# ./fact2 7
Factorial of 7 is 5040
[root@localhost shell]# ./fact2 33
Factorial of 33 is 8683317618811886495518194401280000000

Posted by venu k at 8:41 AM 3 comments

Labels: Beginners Scripts

Monday, October 26, 2009


For Loop Example-2

#!/bin/bash
# Usage: forloop2.sh or forloop2.sh number
# Example using for loop
# Prints following format
# *
# * *
# * * *
# * *
# *

n=${1-10} # If command line argument not supplied default is


10
t=`expr $((2*$n - 1 ))`
a=$n
b=$(($a+1))
for (( i=1 ; i<=$n ;i++ ))
do
echo -e -n "\033[47m"
a=$(($b-1))
b=$a
k=1
for (( j=1 ; j<=$t ; j++ ))
do
if [ $j -eq $a ]
then
echo -e "\033[43m * \033[47m\c"
if [ $k -lt $i ]
then
a=$((a+2))
let k++
fi
else
echo -n " "
fi
done
echo ""
done

n=$(($n-1))
a=1
b=$a
for (( i=$n ; i>=1 ;i-- ))
do
echo -e -n "\033[47m"
a=$(($b+1))
b=$a
k=1
for (( j=1 ; j<=$t ; j++ ))
do
if [ $j -eq $a ]
then
echo -e "\033[43m * \033[47m\c"
if [ $k -lt $i ]
then
a=$((a+2))
let k++
fi
else
echo -n " "
fi
done
echo ""
done
echo -e "\033[0m"
Output:

Posted by venu k at 9:50 AM 0 comments

Labels: Beginners Scripts

Wednesday, October 7, 2009


Bash for loop example-1
#!/bin/bash
# Usage: script.sh number
# A for loop example produces following output
#
# *
# * *
# * * *
# * * * *
#* * * * *
#

Method1
c=1
n=$1
echo -e "\033[47m\c" #colourizing output
for ((row=1;row<=n;row++))
do
for ((i=row;i<n;i++))
do
echo -n ' '
done
for ((k=1;k<=c;k++))
do
if [ $((k%2)) -eq 0 ]
then
echo -n " "
else
echo -e "\033[43m * \033[47m\c"
fi
done
for ((i=row;i<n;i++))
do
echo -n ' '
done
c=$((c+2))
echo
done
echo -e "\033[0m" #Restoring colours
unset c i k n row

Method2
#!/bin/bash
n=$1
t=$((2*n - 1 ))
a=$n
b=$((a+1))
echo -e -n "\033[47m"
for (( i=1 ; i<=$n ;i++ ))
do
a=$(($b-1))
b=$a
k=1
for (( j=1 ; j<=$t ; j++ ))
do
if [ $j -eq $a ]
then

echo -e "\033[43m * \033[47m\c"


if [ $k -lt $i ]
then

a=$((a+2))
let k++
fi
else
echo -n " "
fi

done
echo
done
echo -e "\033[0m"
Output:

Posted by venu k at 8:19 AM 0 comments

Labels: Beginners Scripts

Shell Script To Print Pyramid - Using while Loop

#!/bin/bash
# Usage: scriptname argument
# Here argument is height of pyramid
# Output would be pyramid pattern of stars
# 0 *
# 1 ***
# 2 *****
# 3 *******
# 4 *********
# 5 ***********
# 6 *************
# . ***************
# . *****************
# . *******************
# n-1 *********************
# ---\/--- | ---\/---
# n-1 n-1
#
clear
n=$1
row=1;
echo -e "\033[47m"
while [[ $row -le $n ]]
do
loop=1;
spaces=$((n-row))
stars=$((2*row - 1))

while [[ $loop -le $spaces ]]


do
echo -n ' '
let loop++
done
loop=1;
while [[ $loop -le $stars ]]
do
echo -e '\033[43m*\033[47m\c'
let loop++
done
loop=1;
while [[ $loop -le $spaces ]]
do
echo -n ' '
let loop++
done
echo
let row++
done
echo -e "\033[0m"
unset row loop spaces stars n
Output:
[root@localhost blog]# sh while_pyramid 22

Posted by venu k at 6:10 AM 1 comments

Labels: Beginners Scripts

Shell Script To Print Pyramid-Using for Loop


#!/bin/bash
# Usage: scriptname argument
# Here argument is height of pyramid
# Output would be pyramid pattern of stars
# 0 *
# 1 ***
# 2 *****
# 3 *******
# 4 *********
# 5 ***********
# 6 *************
# . ***************
# . *****************
# . *******************
# n-1 *********************
# ---\/--- | ---\/---
# n-1 n-1
#

Showing newest posts with label Article. Show older posts

Friday, May 14, 2010


How to Read a File Line by Line in a Shell Script

There are many ways to handle any task on a Unix platform, but
some
techniques that are used to process a file waste a lot of CPU time.
Most of the wasted time is spent in unnecessary variable assignment
and
continuously opening and closing the same file over and over. Using
a
pipe also has a negative impact on the timing.

In this article I will explain various techniques for parsing a


file
line by line. Some techniques are very fast and some make you wait
for
half a day. The techniques used in this article are measurable, and
I
tested each technique with time command so that you can see which
tec-
hniques suits your needs.

I don't explain in depth every thing, but if you know basic shell
scripting, I hope you can understand easily.

I extracted last five lines from my /etc/passwd file, and stored


in a
file "file_passwd".

[root@www blog]# tail -5 /etc/passwd > file_passwd


[root@www blog]# cat file_passwd
venu:x:500:500:venu madhav:/home/venu:/bin/bash
padmin:x:501:501:Project Admin:/home/project:/bin/bash
king:x:502:503:king:/home/project:/bin/bash
user1:x:503:501::/home/project/:/bin/bash
user2:x:504:501::/home/project/:/bin/bash

I use this file whenever a sample file required.

Method 1: PIPED while-read loop

#!/bin/bash
# SCRIPT: method1.sh
# PURPOSE: Process a file line by line with PIPED while-read loop.

FILENAME=$1
count=0
cat $FILENAME | while read LINE
do
let count++
echo "$count $LINE"
done

echo -e "\nTotal $count Lines read"

With catting a file and piping the file output to a while read
loop a
single line of text is read into a variable named LINE on each loop
iteration. This continuous loop will run until all of the lines in
the
file have been processed one at a time.

Bash can sometimes start a subshell in a PIPED "while-read" loop.


So
the variable set within the loop will be lost (unset) outside of
the
loop. Therefore, $count would return 0, the initialized value
outside
the loop.

Output:

[root@www blog]# sh method1.sh file_passwd


1 venu:x:500:500:venu madhav:/home/venu:/bin/bash
2 padmin:x:501:501:Project Admin:/home/project:/bin/bash
3 king:x:502:503:king:/home/project:/bin/bash
4 user1:x:503:501::/home/project/:/bin/bash
5 user2:x:504:501::/home/project/:/bin/bash

Total 0 Lines read


Method 2: Redirected "while-read" loop

#!/bin/bash
#SCRIPT: method2.sh
#PURPOSE: Process a file line by line with redirected while-read
loop.

FILENAME=$1
count=0

while read LINE


do
let count++
echo "$count $LINE"

done < $FILENAME

echo -e "\nTotal $count Lines read"

We still use the while read LINE syntax, but this time we feed the
loop from the bottom (using file redirection) instead of using a
pipe.
You will find that this is one of the fastest ways to process each
line of a file. The first time you see this it looks a little
unusual,
but it works very well.

Unlike method 1, with method 2 you will get total number of lines
out
side of the loop.

Output:

[root@www blog]# sh method2.sh file_passwd


1 venu:x:500:500:venu madhav:/home/venu:/bin/bash
2 padmin:x:501:501:Project Admin:/home/project:/bin/bash
3 king:x:502:503:king:/home/project:/bin/bash
4 user1:x:503:501::/home/project/:/bin/bash
5 user2:x:504:501::/home/project/:/bin/bash

Total 5 Lines read

Note: In some older shell scripting languages, the redirected loop


would also return as a subshell.

Method 3:while read LINE Using File Descriptors

A file descriptor is simply a number that the operating system


assigns
to an open file to keep track of it. Consider it a simplified
version
of a file pointer. It is analogous to a file handle in C.

There are always three default "files" open, stdin (the keyboard),
stdout (the screen), and stderr (error messages output to the
screen).
These, and any other open files, can be redirected. Redirection
simply
means capturing output from a file, command, program, script, or
even
code block within a script and sending it as input to another
file,
command, program, or script.

Each open file gets assigned a file descriptor. The file


descriptors
for stdin,stdout, and stderr are 0,1, and 2, respectively. For
opening
additional files, there remain descriptors 3 to 9 (may be vary
depend-
ing on OS). It is sometimes useful to assign one of these
additional
file descriptors to stdin, stdout, or stderr as a temporary
duplicate
link. This simplifies restoration to normal after complex
redirection
and reshuffling .

There are two steps in the method we are going to use. The first
step
is to close file descriptor 0 by redirecting everything to our new
file
descriptor 3. We use the following syntax for this step:

exec 3<&0

Now all of the keyboard and mouse input is going to our new file
des-
criptor 3. The second step is to send our input file, specified by
the
variable $FILENAME, into file descriptor 0 (zero), which is
standard
input. This second step is done using the following syntax:

exec 0<$FILENAME

At this point any command requiring input will receive the input
from
the $FILENAME file. Now is a good time for an example.

#!/bin/bash
#SCRIPT: method3.sh
#PURPOSE: Process a file line by line with while read LINE Using
#File Descriptors

FILENAME=$1
count0=
exec 3<&0
exec 0< $FILENAME

while read LINE


do
let count++
echo "$count $LINE"
done

exec 0<&3
echo -e "\nTotal $count Lines read"

while loop reads one line of text at a time.But the beginning of


this
script does a little file descriptor redirection. The first exec
comm-
and redirects stdin to file descriptor 3. The second exec command
red-
irects the $FILENAME file into stdin, which is file descriptor 0.
Now
the while loop can just execute without our having to worry about
how
we assign a line of text to the LINE variable. When the while loop
exits we redirect the previously reassigned stdin, which was sent
to
file descriptor 3, back to its original file descriptor 0.

exec 0<&3

In other words we set it back to the system’s default value.

Output:

[root@www tempdir]# sh method3.sh file_passwd


1 venu:x:500:500:venu madhav:/home/venu:/bin/bash
2 padmin:x:501:501:Project Admin:/home/project:/bin/bash
3 king:x:502:503:king:/home/project:/bin/bash
4 user1:x:503:501::/home/project/:/bin/bash
5 user2:x:504:501::/home/project/:/bin/bash
Total 5 Lines read

Method 4: Process file line by line using awk

awk is pattern scanning and text processing language. It is useful


for manipulation of data files, text retrieval and processing. Good
for manipulating and/or extracting fields (columns) in structured
text files.

Its name comes from the surnames of its authors: Alfred Aho, Peter
Weinberger, and Brian Kernighan.

I am not going to explain everything here.To know more about awk


just
Google it.

At the command line, enter the following command:

$ awk '{ print }' /etc/passwd

You should see the contents of your /etc/passwd file appear before
your eyes.Now, for an explanation of what awk did. When we called
awk,
we specified /etc/passwd as our input file. When we executed awk,
it
evaluated the print command for each line in /etc/passwd, in
order.All
output is sent to stdout, and we get a result identical to catting
/etc/passwd. Now, for an explanation of the { print } code block.
In
awk, curly braces are used to group blocks of code together,
similar
to C. Inside our block of code,we have a single print command. In
awk,
when a print command appears by itself, the full contents of the
curr-
ent line are printed.

Here is another awk example that does exactly the same thing:

$ awk '{ print $0 }' /etc/passwd

In awk, the $0 variable represents the entire current line, so


print
and print $0 do exactly the same thing. Now is a good time for an
example.
#!/bin/bash
#SCRIPT: method4.sh
#PURPOSE: Process a file line by line with awk

FILENAME=$1

awk '{kount++;print kount, $0}


END{print "\nTotal " kount " lines read"}' $FILENAME

Output:

[root@www blog]# sh method4.sh file_passwd


1 venu:x:500:500:venu madhav:/home/venu:/bin/bash
2 padmin:x:501:501:Project Admin:/home/project:/bin/bash
3 king:x:502:503:king:/home/project:/bin/bash
4 user1:x:503:501::/home/project/:/bin/bash
5 user2:x:504:501::/home/project/:/bin/bash

Total 5 lines read

Awk is really good at handling text that has been broken into
multiple
logical fields, and allows you to effortlessly reference each
individ-
ual field from inside your awk script. The following script will
print
out a list of all user accounts on your system:

awk -F":" '{ print $1 "\t " $3 }' /etc/passwd

Above, when we called awk, we use the -F option to specify ":" as


the
field separator. By default white space (blank line) act as filed
sep-
arator. You can set new filed separator with -F option. When awk
proc-
esses the print $1 "\t " $3 command, it will print out the first
and
third fields that appears on each line in the input file. "\t" is
used
to separate field with tab.

Method 5: Little tricky with head and tail


commands

#!/bin/bash
#SCRIPT: method5.sh
#PURPOSE: Process a file line by line with head and tail commands
FILENAME=$1
Lines=`wc -l < $FILENAME`

count=0

while [ $count -lt $Lines ]


do
let count++
LINE=`head -n $count $FILENAME | tail -1`
echo "$count $LINE"
done
echo -e "\nTotal $count lines read"

On each iteration head command extracts top $count lines, then tail
command extracts bottom line from that lines. A very stupid method,
but some people still using it.

Output:

[root@www blog]# sh method5.sh file_passwd


1 venu:x:500:500:venu madhav:/home/venu:/bin/bash
2 padmin:x:501:501:Project Admin:/home/project:/bin/bash
3 king:x:502:503:king:/home/project:/bin/bash
4 user1:x:503:501::/home/project/:/bin/bash
5 user2:x:504:501::/home/project/:/bin/bash

Total 5 lines read

Time Comparison for the Five Methods

Now take a long breath, we are going test each technique. Before
you
get into test each method of parsing a file line by line create a
large
file that has the exact number of lines that you want to process.
Use bigfile.sh script to create a large file.

$ sh bigfile.sh 900000

bigfile.sh with 900000 lines as an argument,it has taken more than


two
hours to generate bigfile.4227. I don't know exactly how much time
it
has taken. This file is extremely large to parse a file line by
line,
but I needed a large file to get the timing data greater than zero.
[root@www blog]# du -h bigfile.4227
70M bigfile.4227
[root@www blog]# wc -l bigfile.4227
900000 bigfile.4227

[root@www blog]# time ./method1.sh bigfile.4227 >/dev/null

real 6m2.911s
user 2m58.207s
sys 2m58.811s
[root@www blog]# time ./method2.sh bigfile.4227 > /dev/null

real 2m48.394s
user 2m39.714s
sys 0m8.089s
[root@www blog]# time ./method3.sh bigfile.4227 > /dev/null

real 2m48.218s
user 2m39.322s
sys 0m8.161s
[root@www blog]# time ./method4.sh bigfile.4227 > /dev/null

real 0m2.054s
user 0m1.924s
sys 0m0.120s
[root@www blog]# time ./method5.sh bigfile.4227 > /dev/null
I waited more than half day, still i didn't get result, then I
created
a 10000-line file to test this method.
[root@www tempdir]# time ./method5.sh file.10000 > /dev/null

real 2m25.739s
user 0m21.857s
sys 1m12.705s

Method 4 came in first place,it has taken very less time 2.05
seconds,
but we can't compare Method 4 with other methods, because awk is
not
just a command, but a programming language too.

Method 2 and method 3 are tied for second place, they produce
mostly
the same real execution time at 2 minutes and 48 seconds . Method 1
came in third at 6 minutes and 2.9 seconds.

Method 5 has taken more than half a day. 2 minutes 25 seconds to


pro-
cess just a 10000 line file, how stupid it is.

Note: If file contain escape characters, use read -r instead of


read,
then Backslash does not act as an escape character. The back-slash
is
considered to be part of the line. In particular, a backslash-
newline
pair may not be used as a line continuation.

Posted by venu k at 11:45 PM 4 comments

Labels: Article

Sunday, April 18, 2010


How to Handle Cursor Movement in a Shell Script

Using ANSI escape sequences :

ANSI escape sequences or tput allow you to move the cursor around
the
screen at will. This is more useful for full screen user interfaces
generated by shell scripts, but can also be used in prompts.

The movement escape sequences are as follows:

- Position the Cursor:


\033[;H
Or
\033[;f
puts the cursor at line L and column C.
- Move the cursor up N lines:
\033[A
- Move the cursor down N lines:
\033[B
- Move the cursor forward N columns:
\033[C
- Move the cursor backward N columns:
\033[D
- Clear the screen, move to (0,0):
\033[2J
- Erase to end of line:
\033[K
- Save cursor position:
\033[s
- Restore cursor position:
\033[u

The latter two codes are NOT honored by many terminal emulators.
The
only ones that I'm aware of that do are xterm and nxterm - even
though
the majority of terminal emulators are based on xterm code. As far
as
I can tell, rxvt, kvt, xiterm, and Eterm do not support them. They
are
supported on the console.

$ echo -en "\033[s\033[7B\033[1;34m BASH BASH\033[u\033[0m"

This should saves the current cursor position(\033[s), then move


the
cursor seven lines down the screen(\o33[7B),print the word "BASH
BASH"
in dark blue color(\033[1;34m), and then return to where it started
to
produce a normal prompt(\033[u), and also back to the normal color
(\033[0m).

Example:

$ echo -en "\033[s\033[7B\033[1;34m BASH BASH\033[u\033[0m"


$

BASH BASH

Using tput command:

As with so many things in Unix, there is more than one way to


achieve
the same ends.A utility called tput can also be used to move the
cursor
around the screen, get back information about the status of the
termi-
nal, or set colors.

man tput doesn't go into much detail about the available


commands,but
man terminfo will give you a huge list of capabilities, many of
which
are device independent, and therefore better than the escape
sequences
previously mentioned.

Here is some useful tput capabilities:

tput Cursor Movement Capabilities:

tput cup Y X
Move cursor to screen location X,Y (top left is 0,0)

tput sc
Save the cursor position

tput rc
Restore the cursor position

tput lines
Output the number of lines of the terminal

tput cols
Output the number of columns of the terminal

tput cub N
Move N characters left

tput cuf N
Move N characters right
tput cuu N
up N lines

tput cud N
down N lines

tput Colour Capabilities :

tput setab [1-7]


Set a background colour using ANSI escape

tput setb [1-7]


Set a background colour

tput setaf [1-7]


Set a foreground colour using ANSI escape

tput setf [1-7]


Set a foreground colour
tput Text Mode Capabilities:

tput bold
Set bold mode

tput dim
turn on half-bright mode

tput smul
begin underline mode

tput rmul
exit underline mode

tput rev
Turn on reverse mode

tput smso
Enter standout mode (bold on rxvt)

tput rmso
Exit standout mode

tput sgr0
Turn off all attributes (doesn't work quite as expected).

tput Clear and Insert Capabilities :

tput ech N
Erase N characters

tput clear
clear screen and home cursor

tput el1
Clear to beginning of line

tput el
clear to end of line

tput ed
clear to end of screen

tput ich N
insert N characters (moves rest of line forward!)

tput il N
insert N lines
This is by no means a complete list of what terminfo and tput
allow,
in fact it's only the beginning. man tput and man terminfo if you
want
to know more.

Example:

$ tput sc;tput cup 4 35;tput setaf 2;echo "Hello World";\


> tput rc;tput sgr0
$

Hello World

Bellow example shows two different ways to achieve same task:

$ tput sc;tput cud 7;tput setaf 4;echo BASH BASH; tput rc;\
> tput sgr0
$ echo -en "\033[s\033[7B\033[0;34m BASH BASH\033[u\033[0m"

Posted by venu k at 8:19 AM 2 comments

Labels: Article

Saturday, March 27, 2010


UNIX/Linux Advanced File Permissions - SUID,SGID and Sticky Bit

After you have worked for a while with Linux you discover
probably
that there is much more to file permissions than just the "rwx"
bits.
When you look around in your file system you will see "s" and "t"

$ ls -ld /tmp
drwxrwxrwt 29 root root 36864 Mar 21 19:49 /tmp

$ which passwd
/usr/bin/passwd

$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 22984 Jan 6 2007 /usr/bin/passwd

What is this "s" and "t" bit? The vector of permission bits is
really
4 * 3 bits long. Yes there are 12 permission bits,not just 9.The
first
three bits are special and are frequently zero. And you almost
always
learn about the trailing 9 bits first.Some people stop there and
never
learn those first three bits.

The forth permission bit is used only when a special mode of a


file
needs to be set. It has the value 4 for SUID, 2 for SGID and 1 for
the
sticky bit. The other 3 bits have their usual significance.

Here we will discuss about the 3 special attributes other than the
common read/write/execute:

1.Set-User-Id (SUID)
2.Set-Group-Id (SGID)
3.Sticky Bit

Set-User_Id (SUID): Power for a Moment:

By default, when a user executes a file, the process which results


in
this execution has the same permissions as those of the user. In
fact,
the process inherits his default group and user identification.

If you set the SUID attribute on an executable file, the process


res-
ulting in its execution doesn't use the user's identification but
the
user identification of the file owner.

The SUID mechanism,invented by Dennis Ritchie,is a potential


security
hazard. It lets a user acquire hidden powers by running such a file
owned by root.

$ ls -l /etc/passwd /etc/shadow /usr/bin/passwd


-rw-r--r-- 1 root root 2232 Mar 15 00:26 /etc/passwd
-r-------- 1 root root 1447 Mar 19 19:01 /etc/shadow

The listing shows that passwd is readable by all, but shadow is


unre-
adable by group and others. When a user running the program belongs
to
one of these two categories (probably, others), so access fails in
the
read test on shadow. suppose normal user wants to change his
password,
How can he do that? He can do that by running /usr/bin/passwd. Many
UNIX/Linux programs have a special permission mode that lets users
update sensitive system files –like /etc/shadow --something they
can't
do directly with an editor. This is true of the passwd program.

$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 22984 Jan 6 2007 /usr/bin/passwd

The s letter in the user category of the permission field


represents a
special mode known as the set-user-id (SUID). This mode lets a
process
have the privileges of the owner of the file during the instance of
the program. Thus when a non privileged user executes passwd, the
eff-
ective UID of the process is not the user's, but of root's – the
owner
of the program. This SUID privilege is then used by passwd to edit
/etc/shadow.

What is effective user-id:

Every process really has two user IDs: the effective user ID and
the
real user ID. (Of course, there's also an effective group ID and
real
group ID.Just about everything that's true about user IDs is also
true
about group IDs) Most of the time,the kernel checks only the
effective
user ID. For example, if a process tries to open a file, the kernel
checks the effective user ID when deciding whether to let the
process
access the file.

Save the following script under the name reids.pl and make it
executable (chmod 755 reids.pl).

#!/usr/bin/perl
# print real UID
print "Real UID: $<\n";
# print real GID
print "Real GID: $(\n";
# print effective UID
print "Effective UID: $>\n";
# print effective GID
print "Effective GID: $)\n";
check file permissions:

$ ls -l reids.pl
-rwxr-xr-x 1 venu venu 203 Mar 24 10:40 reids.pl

Note: For security reasons the s-bit works only when used on
binaries
(compiled code) and not on scripts (an exception are perl scripts).
Scripts,i.e. programs that cannot be executed by the kernel
directory
but need an interpreter such as the Bourne shell or Java,can have
their setuid bit set, but it doesn't have any effect. There are
some
platforms that honor the s bits even on scripts ( some System V
vari-
ants, for example), but most systems don't because it has proven
such
a security headache - most interpreters simply aren't written with
much security in mind. Set the SUID bit on shell script is useless,
that's why I am using perl script here.

When you run the script you will see that the process that runs it
gets your user-ID and your group-ID:

$ ./reids.pl
Real UID: 500
Real GID: 500 500
Effective UID: 500
Effective GID: 500 500

Note: If you get an error like this:


Can't do setuid (cannot exec sperl)

In Debian install perl-suid using following command:


apt-get install perl-suid

In Centos install perl-suidperl using following command:


yum install perl-suidperl

Now change owner ship to another user (Do it as an


administrator).

# chown king /home/venu/reids.pl


# ls -l /home/venu/reids.pl
-rwxr-xr-x 1 king venu 203 Mar 24 10:40 /home/venu/reids.pl

Now run the script again.


$ ./reids.pl
Real UID: 500
Real GID: 500 500
Effective UID: 500
Effective GID: 500 500

What you observed, the output of the program depends only on the
user
that runs it and not the one who owns the file.

How to assign SUID permission:

The SUID for any file can be set (mostly by the superuser) with a
special syntax of the chmod command. This syntax uses the character
s
as the permission. Now add SUID permission to the script reids.pl :

# chmod u+s /home/venu/reids.pl (Do it from root account)

Now return from the super user mode to the usual non privileged
mode.

$ ls -l reids.pl
-rwsr-xr-x 1 king venu 203 Mar 24 10:40 reids.pl

To assign SUID in an absolute manner, simply prefix 4 to whatever


octal string you would otherwise use (like 4755 instead of 755).

The file reids.pl is owned by king and has the s-bit set where
norma-
lly the x is for the owner of the file. This causes the file to be
executed under the user-ID of the user that owns the file rather
than
the user that executes the file. If venu runs the program then this
looks as follows:

$ perl reids.pl
Real UID: 500
Real GID: 500 500
Effective UID: 503
Effective GID: 500 500

Effective user id of process is 503, this is not the venu's , but


of
king's - the owner of the program. As you can see this is a very
powe-
rful feature especially if root owns the file with s-bit set. Any
user
can then do things that normally only root can do.
Caution: When you write a SUID program then you must make sure
that
it can only be used for the purpose that you intended it to be
used.
As administrator, you must keep track of all SUID programs owned by
root that a user may try to create or copy. The find command easily
locate them:

# find /home -perm -4000 -print | mail root

The extra octal bit (4) signifies the SUID mode, but find treats
the
"–" before 4000 as representing any other permissions.

Set-Group_Id (SGID):

The set-group-id (SGID) is similar to SUID except that a program


with
SGID set allows the user to have the same power as the group which
owns the program. The SGID bit is 2,and some typical examples could
be
chmod g+s reids.pl or chmod 2755 reids.pl.
You can remove SGID bit using following commands:

$ chmod g-s reids.pl


$ chmod 755 reids.pl (Absolute manner)

It is really useful in case you have a real multi-user setup where


users access each others files. As a single homeuser I haven't
really
found a lot of use for SGID. But the basic concept is the same as
the
SUID,Similar to SUID, SGID also grants privileges and access rights
to
the process running the command, but instead of receiving those of
the
file's owner it receives those of the file's group. In other
words,the
process group owner will be set to the file's group.

I explain it with an example. I have created two user accounts


king
and venu with same home directory project. king belongs to king and
development groups, venu belongs to venu and development groups.

# groups king venu


king : king development
venu : venu development
venu's default group is venu and king's default group is king.

Login as king and create reids.pl file again and make it


executable
(using chmod 755 reids.pl) .

$ id
uid=503(king) gid=503(king) groups=501(development),503(king)
$ ls -l reids.pl
-rwxr-xr-x 1 king development 203 Mar 25 19:00 reids.pl

Now login as venu and run the program:

$ id
uid=501(venu) gid=504(venu) groups=501(development),504(venu)
$ perl reids.pl
Real UID: 501
Real GID: 504 504 501
Effective UID: 501
Effective GID: 504 504 501

The effective GID of the process is the venu's,but not of the


king's
-the owner of the program.

Now login as king and assign SGID bit to reids.pl program:

$ chmod 2755 reids.pl; ls -l reids.pl


-rwxr-sr-x 1 king development 203 Mar 25 19:00 reids.pl

Now login as venu and run the reids.pl program:

$ perl reids.pl
Real UID: 501
Real GID: 504 504 501
Effective UID: 501
Effective GID: 501 504 501

Real GID and Effective GID are different,here Effective GID is the
king's - the owner of the program.

Set SGID on a directory:

When SGID is set on a directory it has a special meaning. Files


crea-
ted in a directory with SGID set will inherit the same group
ownership
as the directory itself,not the group of the user who created the
file.
If the SGID is not set the file's group ownership corresponds to
the
user's default group.

In order to set the SGID on a directory or to remove it, use the


following commands:

$ chmod g+s directory or $ chmod 2755 directory


$ chmod g-s directory or $ chmod 755 directory

As I mentioned earlier venu and king's home directory is same that


is
/home/project. I changed group ownership of /home/project directory
to development.

# ls -ld /home/project/
drwxrwxr-x 16 root development 4096 Mar 26 00:22 /home/project/

Now login as king and create a temp file.

$ whoami
king
$ pwd
/home/project/
$ touch temp; ls -l temp
-rw-r--r-- 1 king king 0 Mar 26 12:34 temp

You can see from the ls output that the group owner for project is
development, and that the SGID bit has not been set on the
directory
yet. When king creates a file in project, the group for the file is
king (king's primary gid).

Set SGID bit on project directory. For that login as administrator


and set SGID bit using following command:

# chmod g+s /home/project/


# ls -ld /home/project/
drwxrwsr-x 15 root development 4096 Mar 26 12:34 /home/project/

From the ls output above, you know the SGID bit is set because of
the
s in the third position of the group permission set,which replaces
the
x in the group permissions.

Now login as king and create temp2 file.

$ whoami
king
$ touch temp2; ls -l temp2
-rw-r--r-- 1 king development 0 Mar 26 13:49 temp2

Notice the group ownership for temp2 file. It inherits group


permiss-
ion from the parent directory.

Enabling SGID on a directory is extremely useful when you have a


group of users with different primary groups working on the same
set
of files.

For system security reasons it is not a good idea to set


many
program's set user or group ID bits any more than necessary,since
this
can allow an unauthorized user privileges in sensitive system
areas.If
the program has a flaw that allows the user to break out of the
inten-
ded use of the program, then the system can be compromised.

Sticky bit:

The sticky bit(also called the saved text bit) is the last
permission
bit remaining to be discussed. It applies to both regular files and
directories. When applied to a regular file, it ensures that the
text
image of a program with the bit set is permanently kept in the swap
area so that it can be reloaded quickly when the program's turn to
use
the CPU arrives. Previously, it made sense to have this bit set for
programs like vi and emacs. Today,machines with ultra-fast disk
drives
and lots of cheap memory don't need this bit for ordinary files and
that is also useless.

However, the sticky bit become a useful security feature when used
with a directory. The UNIX/Linux system allows users to create
files
in /tmp, but none can delete files not owned by him. That's
possible
because sticky bit set for /tmp directory.

The /tmp directory is typically world-writable and looks like this


in a listing:
# ls -ld /tmp
drwxrwxrwt 32 root root 36864 Mar 27 12:38 /tmp

Everyone can read,write and access the directory.The t indicates


that
only the user (root and owner of the directory,of course) that
created
a file in this directory can delete that file.

In order to set or to remove the sticky bit, use the following


commands:

$ chmod +t directory or $ chmod 1754 directory


$ chmod -t directory or $ chmod 754 directory

Note: 754 permissions for a directory are powerful enough to guard


your directories from intruders with malicious intentions, that's
why
I used 754 as default,if yow want you can change it.

Example:

I logged in as king and created a temp file.

$ whoami
king
$ pwd
/home/project/
$ touch temp; ls -l
-rw-r--r-- 1 king king 0 Mar 27 13:44 temp

Now logged in as venu and try to delete temp file.

$ whoami
venu
$ rm temp
rm: remove write-protected regular empty file `temp'? Y
$ ls temp
ls: temp: No such file or directory

So what happened? venu deleted file owned by king.

Assign sticky bit to the project directory.As a owner of the


directory
or administrator.

# chmod +t /home/project
# ls -ld /home/project/
drwxrwxr-t 15 root development 4096 Mar 27 13:46 /home/project/
From the ls output above, you know the sticky bit is set because
of
the t in the third position of the other permission set,which
replaces
the x in the other permissions.

Now repeat same steps again,then you get the following message:

$ whoami
venu
$ ls -l temp
-rw-r--r-- 1 king king 0 Mar 27 17:36 temp
$ rm temp
rm: remove write-protected regular empty file `temp'? y
rm: cannot remove `temp': Operation not permitted

Posted by venu k at 10:51 AM 7 comments

Labels: Article

Thursday, March 18, 2010


Linux File and Directory Permissions

What are file permissions:

Every file or folder in Linux has access permissions. There are


three
types of permissions (what allowed to do with a file):

read access (symbolized by the letter r)


write access (symbolized by the letter w)
execute access (symbolized by the letter x)

Permissions are defined for three types of users:

the owner of the file (symbolized by the letter u )


the group that the owner belongs to (symbolized by the letter g)
other users (symbolized by the letter o)

Thus, Linux file permissions are nine bits of information. The


table
below shows the syntax:

1 2 3 4 5 6 7 8 9 10
File User Permissions Group Permissions Other Permissions

Type Read Write Execute Read Write Execute Read Write Execute

d r w e r w e r w e

- > The first character is not a permission bit, it simply


indicates
the type of file as indicated in the table below:

Character Type of file

- regular file

d directory

l symbolic link

s socket

p named pipe

c character device file (unbuffered)

b blocked device file (buffered)

Remaining nine bits are permission bits.

-> Characters 2-4 show owner of the file permissions.


Character 2 indicates read permission, character 3 indicates
write
permission, and character 4 indicates execute permission.
-> Characters 5-7 show group permissions(group to which belong the
file).
Character 5=read, 6=write, 7=execute .
-> Characters 8-10 show permissions for all other users. (users who
are
neither a member of the Group nor the owner of the file)
Character 8=read, 9=write, 10=execute.

Ownership: When you create a file, you automatically become its


owner. The owner has full authority to tamper with a file's
contents
and permissions –a privilege not available with others except the
root
user.Similarly, You can create, modify or remove files in a
directory
if you are the owner of the directory.

Group Ownership: When creating a user account,the system admin-


istrator also assigns the user to some group. People working on a
project are generally assigned a common group, and all files
created
by group members (who have separate user ids) will have the same
group
owner. However, make no mistake : The privileges of the group are
set
by the owner of the file and not by the group members.

ls -l : Listing File Attributes

$ ls -l sample
-rwxr-xr-- 1 king development 0 Mar 15 00:26 sample

ls -l displays most attributes of a file – like its


permissions,size
and ownership details. If file is a directory,to list attributes of
a
directory use “ls -ld”.

As you can see in this example, the "ls -l" command gives a lot of
information about the file "sample":

- Its name, "sample";


- Its permissions, "-rwxr-xr--";
- Its owner, "king";
- Its group, "development";
- And other information time,size,date etc..

Permissions: rwx r-x r--

r Read access is allowed

w Write access is allowed

x Execute access is allowed

- No permissions

The first group (rwx) has all three permissions.The file is


readable,
writable and executable by the owner of the file,King. But do we
Know
who the owner is? Yes we do. The third column shows king as the
owner
and the first permissions group applies to king. You have to log in
with the username king for these privileges to apply to you.

The second group (r-x) has a hyphen in the middle slot, which
indica-
tes the absence of write permission by the group owner of the file.
This group owner is development, and all users belonging to the
devel-
opment group have read and execute permissions only.

The third group (r--) has the write and execute bits absent. This
set
of permissions is applicable to others i.e., those who are neither
the
owner king nor belong to the development group. So this file is not
world writable.

chmod: CHANGING FILE PERMISSIONS

If you are owner of the file you can set different permissions
for
the three categories of users --owner,group, and others.It's
important
that you understand them because a little learning here can be a
dangerous thing.A faulty file permission is a sure recipe for
disaster.

The chmod (change mode) command is used to set the permissions of


one or more files for all three categories of users.It can be run
only
by the user(the owner) and the superuser. The command can be used
in
two ways:

1.In a relative manner by specifying the changes to the


current
permissions.
2.In an absolute manner by specifying the final permissions.

Relative Permissions:

When changing permissions in a relative manner, chmod only


changes
the permissions specified in the command line and leaves the other
permissions unchanged. In this mode it uses the following syntax:
chmod category operation permission filename(s).

Bellow table shows letters to represent category, operation and


permission:
Category Operation Permission

u User + Assigns permission r Read Permission

g Group - Removes permission w Write Permission

o Other = Assigns absolute permission x Execute Permission

a All(ugo)

Now let's consider an example. First create a file temp.

$ cat > temp


Hello world
Ctrl+d
$ ls -l temp
-rw-r--r-- 1 root root 12 Mar 16 13:32 temp

To assign execute permissions to the User of the file temp, we


need
to frame a suitable expression by using appropriate characters from
each of the three columns of above Table. Since the file needs to
be
executable only by the user,the expression required is u+x:

$ chmod u+x temp


$ ls -l temp
-rwxr--r-- 1 root root 12 Mar 16 13:32 temp

The command assigns(+) execute(x) permissions to the user(u), but


other permissions remain unchanged. To enable group and others to
exe-
cute this file, you have to use multiple characters to represent
the
user category(ugo) or simply use a it implies ugo.

$ chmod ugo+x temp


$ ls -l temp
-rwxr-xr-x 1 root root 12 Mar 16 13:32 temp

chmod command also accept more than one file name in the command
line.
When you need to assign the same set of permissions to a group
files,
all the file names have to be specified with a single chmod
command:

$ chmod u+x temp1 temp2 temp3

Permissions are removed with the - operator. To remove the read


permission from both group and others, use the expression go-r:

$ chmod go-r temp ; ls -l temp


-rwx--x--x 1 root root 12 Mar 16 13:32 temp

chmod also accepts multiple expressions delimited by commas. For


instance, to restore the original permissions to the file temp,you
have to remove the execute permission from all(a-x) and assign read
permission to group and others(go+r):

$ chmod a-x,go+r temp; ls -l temp


-rw-r--r-- 1 root root 12 Mar 16 13:32 temp

More than one permission can also be set; u+rwx is a valid chmod
expression.So setting write and execute permissions for others is
no
problem:

$ chmod o+rwx temp; ls -l temp


-rw-r--rwx 1 root root 12 Mar 16 13:32 temp

Absolute Permissions:

Some times you don't need to now what a file's current


permissions
are,but want to set all nine permission bits explicitly.The
expression
used by chmod here is a string of three octal numbers(base 8).Each
type
of permission is assigned a number as shown :

I. Read permission - 4
II. Write permission - 2
III. Execute permission - 1

For each category we add the numbers that represent the


assigned
permissions. For instance, 6 represents read and write
permissions,and
7 represents all permissions.
This table shows what numeric values mean:

Octal digit Text equivalent Meaning

0 --- All types of access are denied

1 --x Execute access is allowed only

2 -w- Write access is allowed only

3 -wx Write and execute access are allowed

4 r-- Read access is allowed only

5 r-x Read and execute access are allowed

6 rw- Read and write access are allowed

7 rwx Everything is allowed

We see that "1" stands for execute only, "2" stands for write
only,
"4" stands for read only.To combine the permissions you can simply
add
1, 2 and 4 to get a needed combination. For instance, to get read
and
write permissions,you add 4 (read) and 2 (write), thus getting 6
(read
and write). To get read and execute permissions, you add 4 (read)
and
1 (execute), thus getting 5 (read and execute).

To take a simple example,if a file has read and write permissions


for
the user, the octal representation of the user's permissions will
be
4 + 2 = 6. When this exercise is repeated for the other categories,
the
result will be a three character string representing three octal
digi-
ts, with each octal digit indicating the permissions for the
category.
The sequence followed is user,group and others. You can use this
method
to assign read and write permissions to all three categories.
Examples:

To assign all permissions to the owner,read and write permissions


to
the group,and only execute permission to the others, use this:

$ chmod 761 sample ; ls -l sample


-rwxrw---x 1 king development 0 Mar 15 00:26 sample

Assign yourself full access to read and modify the file,allow


members
of the group to read it and do not allow any others access:

$ chmod 640 sample ; ls -l sample


-rw-r----- 1 king development 0 Mar 15 00:26 sample

Some octal permissions and their meaning:

Permissions Meaning

owner: read and write permissions,


644 group: only read permissions,
others: only read permissions.

owner: read, write and execute permissions,


755 group: read and execute permissions,
others: read and execute permissions.

owner: read, write and execute permissions,


754 group: read and execute permissions,
others: only read permissions.

As long as you're the owner of a file, you can use the chmod
command
to set the permissions any way you like.

umask: Default file and Directory permissions:

The UNIX system has the following default permissions for all
files
and directories:

rw-rw-rw-(octal 666) for regular files.


rwxrwxrwx(octal 777) for directories.

However,you don't see these permissions when you create a file or


a
directory. To understand this let us first create an empty file
called
sample using the touch command and then try to list it.

$ touch sample ; ls -l sample


-rw-r--r-- 1 king development 0 Mar 18 00:41 sample

How come that the file permissions for this file have been set to
644
What Unix does is it uses the value stored in a variable called
umask
to decide the default permissions. The umask value tells Unix which
of
the three permissions are to be denied rather than granted.The
current
value of umask can be easily determined by just typing umask.

$ umask
0022

Here, the first 0 indicates that what follows is an octal


number.This
octal number which has to be subtracted from the system default to
ob-
tain the actual default. This becomes 644 (666-022) for ordinary
files
and 755 (755-022) for directories.When you crate a file on this
system
,it will have the permissions rw-r--r--.

umask is a shell built-in command though it also exists as an


external
command. A user can also use this command to set a new default.
Here's
an extreme setting:

$ umask 000 All read-write permissions on

For instance, if you want all new directories to get permissions


rwxr-xr--- and files to get permissions rw-r----- by default(modes
750
and 640), you'll need to use a umask value which removes all rights
to
other,and write permissions to the group : 027. The command to use
is:
$ umask 027

A umask value of 000 means that you haven't subtracted anything,


and
this could be a dangerous. The system's default then applies (666
for
files and 777 for directories). All files and directories are then
writable by all; nothing could be worse than that! However, a
mask
value of 666 or 777 doesn't make much sense either; you'll then be
cr-
eating files and directories with no permissions.

One important thing to remember is that,no one not even the


administ
rator can turn on permissions not specified in the system wide
default
settings. However you can always use chmod as and when required.
The
system wide umask setting is placed in one of the machine's startup
scripts, and is automatically made available to all users.

Directory Permissions:

Unix treats every thing as a file, directories too are treated


by
Unix as files.A directory, as Unix perceives, is a file which
contains
the names of the files present in the directory.Hence a read
permission
on a directory allows the listing of the directory contents and
nothing else.

Directories also have their own permissions and the


significance
of these permissions differ from those of ordinary files. Read and
write access to an ordinary file are also influenced by the
permissio-
ns of the directory housing them. It's possible that a file can't
be
accessed even though it has read permission, and can be removed
even
when it's is write protected.

Here are some typical permissions required on directories:

To understand permissions first create temp directory and create


some
files in that directory.

$ mkdir temp
$ cd temp
$ touch a b
$ pwd
/home/project/temp
$ ls -l
total 8
-rw-r--r-- 1 king development 0 Mar 18 18:56 a
-rw-r--r-- 1 king development 0 Mar 18 18:56 b

-> Execute permission is required for a user to cd into a


directory.

change temp directory permissions to 400(Read only permission).


Then try to change directory, you won't be permitted.

$ chmod 400 temp


$ cd temp
cd: temp: Permission denied
$ ls temp
a b

-> Read permission is required for a user to use a command such as


ls
to view the files contained in a directory.

$ chmod 300 temp


$ ls temp
ls: temp: Permission denied
$ cd temp
$ pwd
/home/project/temp

-> Execute-only permission allows a user to access the files in a


directory as long as the user knows the names of the files in the
directory, and the user is allowed to read the files.

$ chmod 100 temp


$ ls temp/
ls: temp/: Permission denied
$ cat temp/a
Hello world

-> Write permission allows the user to create, delete, or modify


any
files or sub directories, even if the file or sub directory is
owned by
another user.

Difference in access permissions for files and


directories:

Access permissions for files and folders mean different things


from
the user standpoint. The table below shows the difference.

Access type File Directory

If the file contents can If the directory listing can


Read
be read be obtained

If user or process can change


If user or process can
directory contents somehow: create
Write write to the file
new or delete existing files in the
(change its contents)
directory or rename files.

If user or process can access the


If the file can directory, that is, go to it (make
Execute
be executed it to be the current working direc
tory)

Posted by venu k at 8:41 AM 0 comments

Labels: Article

Friday, January 1, 2010


Shell Colors: colorizing shell scripts

Shell scripts commonly used ANSI escape codes for color


output.
Following table shows Numbers representing colors in Escape
Sequences.
Color Foreground Background

Black 30 40

Red 31 41

Green 32 42

Yellow 33 43

Blue 34 44

Magenta 35 45

Cyan 36 46

White 37 47

The numbers in the above table work for xterm terminal.Result may
vary
for other terminal emulators.

Use the following template for writing colored text.

echo -e "\033[COLORm Sample text"

The "\033[" begins the escape sequence.You can also use "\e["
instead
of "\033[". COLOR specifies a foreground color, according to the
table
above.The "m" terminates escape sequence, and text begins
immediately
after that.

Note: With an echo, the -e option enables the escape sequences.You


can
also use printf instead of echo.

printf "\e[COLORm sample text\n"


To print Green text

echo -e "\033[32m Hello World"


or
printf "\e[32m Hello World"

The problem with above statement is that the blue color that starts
with the 32 color code is never switched back to the regular color,
so
any text you type after the prompt and even prompt also is still in
the
Green color.

To return to the plain, normal mode, we have yet another sequence.

echo -e "\033[0m"

Now you won't see anything new on the screen, as this echo
statement
was not passed any string to display. But it has done its job,
which
was to restore the normal viewing mode. Whatever yor type now will
be
avoid of any fancy effects.

Escape sequence also allow you to control the manner in which


characters are displayed on the screen.

The following table summarizes numbers representing text attributes


in Escape Sequences.

ANSI CODE Meaning

0 Normal Characters
1 Bold Characters

4 Underlined Characters

5 Blinking Characters

7 Reverse video Characters

Note: Blink attribute doesn't work in any terminal emulator, but it


will work on the console.

Combining all these Escape Sequences, you can get more fancy
effect.
Use the following template for writing colored text on a colored
background.

echo -e "\033[COLOR1;COLOR2m sample text\033[0m";

The semicolon separated numbers "COLOR1" and "COLOR2" specify a


foreground and a background color.The order of the numbers does not
matter, since the foreground and background numbers fall in non-
overlapping ranges."m" terminates the escape sequence, and the text
begins immediately after that.Although setting the colors
separately
also work (i.e. \033[44m\033[32m).

There are some differences between colors when combining colors


with
bold text attribute.

The following table summarises these differences.


Bold off color Bold on color

0;30 Balck 1;30 Dark Gray

0;31 Red 1;31 Dark Red

0;32 Green 1;32 Dark Green

0;33 Brown 1;33 Yellow

0;34 Blue 1;34 Dark Blue

0;35 Magenta 1;35 Dark Magenta

0;36 Cyan 1;30 Dark Cyan

0;37 Light Gray 1;30 White

The following shell script prints all the colors and codes on the
screen.

#!/bin/bash
# This script echoes colors and codes

echo -e "\n\033[4;31mLight Colors\033[0m \t\t\t \033[1;4;31mDark


Colors\033[0m"
echo -e " \e[0;30;47m Black \e[0m 0;30m \t\t \e[1;30;40m Dark
Gray \e[0m 1;30m"
echo -e " \e[0;31;47m Red \e[0m 0;31m \t\t \e[1;31;40m Dark
Red \e[0m 1;31m"
echo -e " \e[0;32;47m Green \e[0m 0;32m \t\t \e[1;32;40m Dark
Green \e[0m 1;32m"
echo -e " \e[0;33;47m Brown \e[0m 0;33m \t\t \e[1;33;40m
Yellow \e[0m 1;33m"
echo -e " \e[0;34;47m Blue \e[0m 0;34m \t\t \e[1;34;40m Dark
Blue \e[0m 1;34m"
echo -e " \e[0;35;47m Magenta \e[0m 0;35m \t\t \e[1;35;40m Dark
Magenta\e[0m 1;35m"
echo -e " \e[0;36;47m Cyan \e[0m 0;36m \t\t \e[1;36;40m Dark
Cyan \e[0m 1;36m"
echo -e " \e[0;37;47m Light Gray\e[0m 0;37m \t\t \e[1;37;40m
White \e[0m 1;37m"
OUTPUT:

Some examples:

Block background and white text

echo -e "\033[40;37m Hello World\033[0m"

Reverse video text attribute option interchanges fg and bg colors.


Bellow statement prints block on white

echo -e "\033[40;37;7m Hello World\033[0m"

echo -e "\033[33;44m Yellow text on blue background\033[0m"


echo -e "\033[1;33;44m Bold yellow text on blue background\033[0m"
echo -e "\033[1;4;33;44mBold yellow underlined text on blue
background\033[0m"

The "tput" command:

Other than echo there is a command called tput using which


we
can control the way the output is displayed on the screen.But it is
less flexible than ANSI escape sequences.

Posted by venu k at 2:17 AM 3 comments

Labels: Article

Sunday, November 15, 2009


How to Pass Arguments to Shell Script

Like UNIX commands, shell scripts also accept arguments from the command
line.
They can, therefore, run non interactively and be used with redirection
and
pipelines.

Positional Parameters:
Arguments are passed from the command line into a shell program using the
positional parameters $1 through to $9. Each parameter corresponds to the
position of the argument on the command line.

The first argument is read by the shell into the parameter $1, The second
argument into $2, and so on. After $9, the arguments must be enclosed in
brackets, for example, ${10}, ${11}, ${12}.Some shells doesn't support
this
method. In that case, to refer to parameters with numbers greater than 9,
use
the shift command; this shifts the parameter list to the left.$1 is
lost,while
$2 becomes $1, $3 becomes $2, and so on. The inaccessible tenth parameter
becomes $9 and can then be referred to.

Example:

#!/bin/bash
# Call this script with at least 3 parameters, for example
# sh scriptname 1 2 3

echo "first parameter is $1"

echo "Second parameter is $2"

echo "Third parameter is $3"

exit 0

Output:
[root@localhost ~]# sh parameters.sh 47 9 34

first parameter is 47

Second parameter is 9

Third parameter is 34

[root@localhost ~]# sh parameters.sh 4 8 3

first parameter is 4

Second parameter is 8

Third parameter is 3

In addition to these positional parameters, there are a few other special


parameters used by shell.Their significance is noted bellow.
$* - It stores the complete set of positional parameters as a single
string.
$@ - Same as $*, But there is subtle difference when enclosed in double
quotes.
$# -It is set to the number of arguments specified.This lets you design
scripts
that check whether the right number of arguments have been entered.
$0------ Refers to the name of the script itself.

Setting Values of Positional Parameters


You can't technically call positional parameters as shell variables
because all
variable names start with a letter. For instance you can't assign values
to $1,
$2.. etc. $=100 or $2=venu is simply not done. There is one more way to
assign
values to the positional parameters, using the set command.

$ set Helping hands are holier than praying lips

The above command sets the value $1 with “Helping” , $2 with “hands” and
so on.
To verify, use echo statement to display their values.

$ echo $1 $2 $3 $4 $5 $6 $7

Helping hands are holier than praying lips

You can simply use $* or $@

$ echo $*

Helping hands are holier than praying lips

$ echo $@

Helping hands are holier than praying lips

Using Shift on Positional Parameters


We have used set command to set upto 9 words. But we can use it for more.

$set A friend who helps when one is in trouble is a real friend

$ echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11

A friend who helps when one is in trouble A0 A1

Observe that last two words in the output. These occurred in the output
because
at a time we can access only 9 positional parameters. When we tried to
refer to
$10 it was interpreted by the shell as if you wanted to out put the value
of $1
and a 0. Hence we got A0 in the output.
Does that mean the words following the ninth word have been lost? No. If
not,
then where have they gone?. They are very much there, safe with the shell
But to
reach them we must do the following.

$shift 4
$ echo $1 $2 $3 $4 $5 $6 $7 $8 $9

when one is in trouble is a real friend

Now where have the first seven words gone? They have been shifted out.The
first
four words lost for ever, as we did not take the precaution to store them
else-
where. What should we have done is:

$ set A friend who helps when one is in trouble is a real friend

$ a=$1

$ b=$2

$ c=$3

$ d=$4

$ shift 4

$ echo $a $b $c $d $1 $2 $3 $4 $5 $6 $7 $8 $9

A friend who helps when one is in trouble is a real friend

Note:In the Korn and bash shells you can refer directly to arguments
where
n is greater than 9 using braces. For example, to refer to the 57th
positional
parameter, use the notation ${57}.some shells may not support this method.

$ set A friend who helps when one is in trouble is a real friend

$ echo ${12}

real

$ echo ${13}

friend

Bracket notation for positional parameters leads to a fairly simple way


of
referencing the last argument passed to a script on the command line.

$ echo ${!#}

friend

$* and $@
Let us look at the subtle difference between $* and $@.

First create three files fileA, fileB, “file temp”


cat > fileA
I LOVE INDIA
Ctrl+d

cat > fileB


HELLO WORLD
Ctrl+d

cat > temp\ file


This file name contains blank space
Ctrl+d

Example:

#!/bin/bash
# Usage: sh arguments.sh fileA fileB temp\ file
cat $*
cat $@
exit 0

Run above script

Output:
[root@localhost temp]# sh arguments.sh fileA fileB temp\ file

I LOVE INDIA

HELLO WORLD

cat: temp: No such file or directory

cat: file: No such file or directory

I LOVE INDIA

HELLO WORLD

cat: temp: No such file or directory

cat: file: No such file or directory

So there is no difference between cat $* and cat $@


Modify arguments.sh script as

#!/bin/bash
# Usage: sh arguments.sh fileA fileB temp\ file
cat “$*”
cat “ $@”
exit 0

Then run the script

Output:
[root@localhost temp]# sh arguments.sh fileA fileB temp\ file

cat: fileA fileB temp file: No such file or directory

I LOVE INDIA

HELLO WORLD

This file name contain blank space

Now there is a difference, the two cat commands would become

cat “fileA fileB temp file”


cat fileA fileB 'temp file'

On execution, the first of these commands would give an error since there
does
not exist a file with the name “fileA fileB temp file”. As against this,
the
second cat command would display the contents of the files fileA, fileB
and
“temp file”.So what you observed,when not enclosed within “” $* and $@
behaves
exactly similarly
Posted by venu k at 1:19 AM 8 comments

Labels: Article

Saturday, October 10, 2009


How to Execute a Shell Script
Defining the Shell Type
To make a bash script crate a new file with a starting line
like:
#!/bin/bash
It is important that the path to the bash is proper and
first two characters must be “#!” . The shell from which you
are starting the script will find this line and hand the whole
script over to bash. Without this line the script would be
interpreted by the same type of shell as the one, from which
it was started.But since the syntax is different for all shells,
it is necessary to define the shell with that line.
Some typical interpreters for shebang lines:

• #!/bin/bash — Execute using the Bourn-again shell


• #!/bin/sh — Execute using the Bourn shell (if available) or a
Bourne compatible shell such as Bourne-again shell
• #!/usr/bin/ksh --- Execute using korn shell

Note:
In computing, a shebang (also called a hashbang, hashpling,
pound bang, or crunchbang) refers to the characters "#!" when
they are the first two characters in a text file. In a Unix-like
operating system, the program loader takes the presence of these
two characters as an indication that the file is a script, and
tries to execute that script using the interpreter specified by
the rest of the first line in the file. For instance, shell
scripts for the Bourne shell start with the first line:
#!/bin/sh

Executing a shell script


Once a shell script is created, there are several ways to
execute it. However, before executing a shell script you must
assign proper permissions. Using chmod command you can change
file permissions.For example giving execute permission to the
file “temp”:
chmod +x temp
First create a sample shell script “temp”.

$cat > temp


#!/bin/bash
echo "My name is `whoami`"
echo "Users are `users`"
echo "OS name is `uname -s`"
echo "current shell is $SHELL"
ctrl+d

Method 1 to execute a shell script:


./scriptname

You must assign execute permission to the script.


With this method script is executed by interpreter which is
defined at sha-bang line.

Note: Script path should be relative to the current


directory then only this method works. If you want to execute a
script in the current directory you use ./scriptname. In fact if
you want to execute a script in the parent directory of your
current location you can use ../scriptname , as . means current
and .. means parent.

Run temp script.

[root@localhost shell]# ./temp


My name is root
Users are root root
OS name is Linux
current shell is /bin/bash

now change sha-bang line with #!/bin/ksh and execute the script

[root@localhost shell]# ./temp


bash: ./temp: /bin/ksh: bad interpreter: No such file or
directory

now change sha-bang line with #!/bin/zsh and execute the script

[root@localhost shell]# ./temp


My name is root
Users are root root
OS name is Linux
current shell is /bin/bash

So wrong path to interpreter or bad interpreter gives error


message.

Method 2 to execute a shell script:


you can execute the bash script by specifying the filename
as an argument to the bash,sh,zsh commands.
This is a bad way to call a script, since it will override
the #! at the beginning of the script.Depending on command you
used, current shell spawns relative subshell.

$sh temp
or
$bash temp
or
$zsh temp
Output:
My name is root
Users are king root root sai venu
OS name is Linux
Current shell is /bin/bash

Note: It is good to use proper command. Suppose your script is


korn shell script,then run it as:
ksh temp

Caution: In this method shell runs script in sub shell.


So you can't access some shell builtin variable values.
For example run bellow shell script:

#!/bin/bash
lines=$LINES
cols=$COLUMNS
echo $lines
echo $cols

Output:
$ sh sample
It prints nothing

Note: To solve this problem export current shell variables


using “export” command.Before executing script, export all
variables you need.

Example:
$ export LINES COLUMNS
$ sh sample
24
80

Method 3 to execute a shell script:


you can execute the bash script by specifying the filename
as an argument to the . (dot) or source command. In this method
script will be run in current shell.
Example:
$ . temp
or
$ source temp
Output:
[root@localhost shell]# . temp
My name is root
Users are king root root sai venu
OS name is Linux
current shell is /bin/bash

[root@localhost shell]# source temp


My name is root
Users are king root root sai venu
OS name is Linux
current shell is /bin/bash

Caution:
Try to unset variables at the end of the script. Otherwise
you will get add results. Variable and functions used in the
script will be alive after execution of the script.

Example:
create two files
cat > sample2
n=100
m=200
echo "n=$n m=$m"
ctrl+d

cat > sample3


n=$((n+m))
m=$((m+25))
echo "n=$n m=$m" ctrl+d

Execute scripts using sh command

[root@localhost shell]# sh sample2


n=100 m=200
[root@localhost shell]# sh sample3
n=0 m=25

Now execute scripts using . Or source command

[root@localhost shell]# . sample2


n=100 m=200
[root@localhost shell]# . sample3
n=300 m=225

So be careful. Try to unset variables at the end of the script.


Method 4 to execute a shell script:
You can also execute scripts by just typing its name alone.
However, for this method to work, the directory containing the
script must be defined in your PATH variable and file must has
executable permission.

For example run “temp” script directly

[root@localhost shell]# temp


bash: temp: command not found

Now add your home directory to PATH variable(I am assuming


script located at home directory).

PATH=${PATH}:$HOME

Now execute script with name, you will get result.

[root@localhost ~]# temp


My name is root
Users are king root root sai venu
OS name is Linux
current shell is /bin/bash

Suppose you changed “temp” script name to “ls”, what will


happen, which result you will get.

[root@localhost ~]# mv temp ls


[root@localhost ~]# ls
Desktop ls sample sample2 sample3

So you will get “ls” command output. Why ?

When you type name of any command at $ prompt, what shell


do is it first look that command in it's internal part(called
as internal command,which is part of shell itself, and always
available to execute),if found as internal command shell will
execute it, 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, other wise it will give message
“bash:XXXX:command not found”.

So don't use command name as shell script.


Note:If you have two different files with same name in different
directories, which file will execute?
The directory which comes first in PATH setting will be
executed.

Example:
First create a file “testscript” in home directory.

$ cat > testscript


whoami
ctrl+d

Then create a directory “bin” in home directory


$ mkdir bin
Now create a file with same name “testscript” in bin dirctory.
$ cd bin
$ cat > testscript
date
ctrl+d

Then add “bin” directory to PATH variable.If your “bin”


directory
already in PATH setting leave it.

PATH=${PATH}:$HOME/bin

now check your path settings

[root@localhost ~]# echo $PATH


/usr/lib/qt-3.3/bin:/usr/kerberos/sbin:/usr/kerberos/bin:
/usr/lib/ccache:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/
bin:/usr/bin:/bin:/root/bin:/root

/root and /root/bin added to your PATH.


I added /root/bin directory before /root directory.

now execute “testscript” script

[root@localhost ~]# testscript


Sat Oct 10 06:57:14 IST 2009
Posted by venu k at 9:55 AM 2 comments

Labels: Article
Wednesday, October 7, 2009
Bash for Loop Syntax
A 'for loop' is a bash programming language statement which allows code to be repeatedly
executed. A for loop is classified as an iteration statement i.e. it is the repetition of a process
within a bash script.

For example, you can run UNIX command or task 5 times or read and process list of files using
a for loop. A for loop can be used at a shell prompt or within a shell script itself.

for loop syntax


Numeric ranges for syntax is as follows:

for VARIABLE in 1 2 3 4 5 .. N
do
command1
command2
commandN
done

Examples:
#!/bin/bah
for i in 1 2 3 4 5
do
echo "Welcome $i times"
done

Using “seq” command

#!/bin/bash
for i in $(seq 1 2 20)
do
echo "Welcome $i times"
done

To know more about “seq” command check manual using “man seq” command

Bash 3.0+ version supports following syntax also

#!/bin/bash
for i in {1..5}
do
echo "Welcome $i times"
done

Three expression syntax


for (( EXP1; EXP2; EXP3 ))
do
command1
command2
command3
done

Example:
#!/bin/bash
for (( c=1; c<=5; c++ ))
do
echo "Welcome $c times..." done

Posted by venu k at 7:58 AM 0 comments

Labels: Article

Sunday, August 23, 2009


What is the difference between Hard Link and Soft Link in Linux
Hard link: Hard link refers to "The specific location of physical data".

 Hard Link is a mirror copy of the original file.


 Hard links share the same inode.
 Any changes made to the original or Hard linked file will reflect the other.
 Even if you delete any one of the files, nothing will happen to the other hard links.
 But soft link which points to deleted hard link become a dangling soft link.
 You can't link a directory even within the same file system.
 Hard links can't cross file systems.

Soft link( also called symbolic link): Soft link refers to "A symbolic path indicating the abstract location
of another file".

 Soft Link is a symbolic link to the original file.(more like windows shortcuts)
 Soft Links will have a different Inode value.
 Any changes made to the soft link will reflect the original file and its hard links.
 A soft link points to the original file. If you delete the original file, the soft link fails. It would
become dangling symbolic link.
 If you delete the soft link, nothing will happen.
 You can link a directory using soft link on same file system and also on other file system.
 Soft links can cross file systems
Lets learn the difference with an example:

First create a file named with "mainfile.txt"

Now create a hard link named with "hardlink.txt"

From the above output you can find inode number of both files are equal.

Now create a soft link named with "softlink.txt"

Now you find that inode value is different for the soft link and main file.

But equal for the hard link and main file.

Contents of all files before editing

Now lets try to edit main file "mainfile.txt"


From the above output it clarifies that, changes of main file reflects its soft and hard links.

Note: Permission changes of original file reflects only on hard links. Its soft links permission
remains unchanged.

Now lets remove main file "mainfile.txt"

So removing the original file will affect the Soft link. The Soft link fails.Now it become a
dangling symbolic link(or broken link).Hard link is unaffected.

Now create main file "mainfile.txt" again and make its links as it is before it is

deleted.

let now try to remove soft link "softlink.txt".


It clarifies that deletion of soft link will not affect the main file and its hard links.

Now lets try to edit hard link "hardlink.tst".Before that create soft link "softlink.txt" again.

From the above output its clear that changing the contents of the hard link will reflects on main
file and also reflect on soft link of main file.

Now lets try to edit the soft link "softlink.txt".


From the above output its clear that changing the contents of soft link will reflects on main file
and also on all links of main file.

Now lets try to remove main file then edit its soft link.

Some strange result.

Soft link creates its main file.But it will not retain main file contents. It merely creates main file
"mainfile.txt" with data what you inserted in "softlink.txt".

Now hard link "hardlink.txt" will not have any relation with main file "mainfile.txt".Both files
now have unique inode value.

Now lets give a look on directories. How soft links and hard links behaves with directories:

Now create a directory named with temp and create some files in that directory.

Now try to create hard link and soft link for directory temp.
Above example clarifies that it's not possible to create hard link on directory but it is possible to
create soft link.

Note:

Like other files, a symbolic link has a separate directory entry with its own inode number. This
means that rm can remove a symbolic link even if its points to a directory(or even a device).

So lets try to remove symbolic link of a directory.In our above example "softtemp" is a symbolic
link for directory temp.

So it clears that we can remove directory symbolic link with rm command just like a file. But
don't add "/" at the end of link(If you use tab to complete file name at command prompt it
automatically adds / at the end of link if it points to a directory).

Observations:

 You can link multiple files (i.e., create a link for each), but then the destination filename must be
a directory.
Ex: ln chap?? project project is a directory

 When you create hard link, The link count of file increases one. So based on link count you can
find how many instances of a file exist in your system.
 So a file is considered to be completely removed from the system when its link count drops to
zero
 Many UNIX/Linux commands are linked.

Ex:

[root@localhost ~]# ls -li /usr/bin/gzip


499116 lrwxrwxrwx 1 root root 14 2008-11-11 03:10 /usr/bin/gzip ->../../bin/gzip

 If you want to create symbolic link of a file in other directory your source file path must be
absolute.
 You can identify symbolic links by the character "l" seen in the permission field.
 Observe that the size of the symbolic link is equal to length of the path name it contains.
 To view the permissions of the file or directory that the symbolic link references, use L
option with ls -l (i.e. ls -lL )
Ex: [root@localhost scripts]# ls -l /usr/bin/gzip
lrwxrwxrwx 1 root root 14 2008-11-11 03:10 /usr/bin/gzip -> ../../bin/gzip
[root@localhost scripts]# ls -lL /usr/bin/gzip
-rwxr-xr-x 1 root root 64524 2008-02-22 02:55 /usr/bin/gzip

Posted by venu k at 7:10 AM 5 comments

Labels: Article

Saturday, June 21, 2008


Bash variables scope

Bash variables are defaults to global

What makes a variable local?

 A variable declared as local is one that is visible only within the block of code in which it appears.
It has local "scope." In a function, a local variable has meaning only within that function block.
Ex:
local variable name

func ()
{
local loc_var=23
# Declared as local variable.
# Uses the 'local' builtin.
echo "\"loc_var\" in function = $loc_var"
global_var=999

# Not declared as local.


# Defaults to global.
echo "\"global_var\" in function = $global_var"
}

func
# Now, to see if local variable "loc_var" exists outside function.

echo "\"loc_var\" outside function = $loc_var"

# $loc_var outside function =


# No, $loc_var not visible globally.

echo "\"global_var\" outside function = $global_var"

# $global_var outside function = 999


# $global_var is visible globally.
exit 0

 Before a function is called, all variables declared within the function are invisible outside the
body of the function, not just those explicitly declared as local

func ()
{
global_var=37

# Visible only within the function block


# before the function has been called.
} # END OF FUNCTION

echo "global_var = $global_var"


# global_var =
# Function "func" has not yet been called,
# so $global_var is not visible here.

func
echo "global_var = $global_var"
# global_var = 37 Has been set by function call.

 Using the declare builtin restricts the scope of a variable

foo ()
{
FOO="bar"
}

bar ()
{
foo
echo $FOO
}

bar
# Prints bar

However . . .

foo (){
declare FOO="bar"
}
bar ()
{
foo
echo $FOO
}
bar
# Prints nothing.

clear
n=$1
echo -e "\033[47m" #used for colourizing output
for ((row=1;row<=n;row++))
do
spaces=$((n-row))
stars=$((2*$row - 1))
for ((i=1;i<=spaces;i++))
do
echo -n ' '
done
for ((i=1;i<=stars;i++))
do
echo -e '\033[43m*\033[47m\c'
done
for ((i=1;i<=spaces;i++))
do
echo -n ' '
done
echo
done
echo -e "\033[0m"
unset n i spaces stars row
# Unset variables is a good programming practice

Output:
[root@localhost blog]# sh for_pyramid 22

Posted by venu k at 5:35 AM 1 comments


Pyramid shell script
Re: Pyramid shell script - please help
I would think about how to do this for a given line, then call it for each size in turn. For
simplicity, lets do it without indenting correctly first:

Shell Scripting Syntax (Toggle Plain Text)

1. function triline() {
2. item=1 # keep track of what to 'store' next
3. linesofar="" # keep track of what is already stored
4. while [ "$item" -le "$1" ]; do # standard while loop starting from
arg1
5. linesofar="$linesofar $item" # store the next item
6. item=$(( item + 1 )) # advance the counter
7. done
8. item=$(( item - 1 )) # the counter is too big. Reduce
9. while [ "$item" -gt 1 ] ; do # standard while loop down to 1
10. item=$(( item - 1 )) # pre-decrement
11. linesofar="$linesofar $item" # store the next item
12. done
13. echo $linesofar # echo the result
14. }

Now you have two remaining tasks:

1. Figure out how to loop through the required number of lines


2. Figure out how to indent

Hint for #1: Use arithmetic as on lines 6, 8 and 10


Hint for #2: linesofar doesn't have to start empty

griswolf
Reputation Points: 174
Solved Threads: 106
Practically a Master Poster
Offline
621 posts
since Apr 2010
Permalink
Oct 7th, 2010
0

Re: Pyramid shell script - please help


Shell Scripting Syntax (Toggle Plain Text)

1. rows=${1:-5} ## Number of rows


2. max=$(( $rows * 4 + 1 )) ## Length of longest row
3.
4. ## If too many rows (or line too long) for window reduce number of rows
5. while [ $max -gt $COLUMNS ] || [ $rows -gt $LINES ]
6. do
7. rows=$(( $rows - 1 ))
8. max=$(( $rows * 4 + 1 ))
9. done
10.
11. ## Build string of stars that is long enough for longest row
12. stars='* * * * * * * * * * * '
13. while [ ${#stars} -lt $max ]
14. do
15. stars=$stars$stars$stars
16. done
17.
18. n=0
19. while [ $(( n += 1 )) -le $rows ]
20. do
21. indent=$(( ($rows - $n) * 2 ))
22. len=$(( $n * 4 ))
23. printf " %${indent}s%$len.${len}s\n" '' "$stars"
24. done

You might also like