EXAMPLE BOURNE SHELL SCRIPTS
The bnl script is the Bourne shell version of the UNIX nl command. It displays line-numbered output.
#!/bin/sh
#
# bnl - Bourne shell line-numbering filter
# A Olczak - ASP, Inc
#
# Initialize line number counter
LNUM=1
# Check usage
if [ "$#" -eq 0 ]
then
echo "Usage: $0 file"
exit 1
fi
# Process each file
for FILE
do
# Make sure file exists
if [ ! -f "$FILE" ]
then
echo "$FILE: non-existent or not accessible"
exit 1
fi
# Read each line, display with line number
cat $FILE | while read LINE
do
echo "$LNUM: $LINE"
LNUM=`expr $LNUM + 1`
done
# Reset line number counter
LNUM=1
done
The kcal script implements a menu-driven calendar program. It supports addition, deletion, modification, and listing of calendar entries. It also provides the ability to find the calendar entry for the current day and list all calendar entries.
#!/bin/sh
#
# bcal - Bourne shell calendar program
#
# Anatole Olczak - ASP, Inc
#
# Check arguments
if [ "$#" -gt 0 ]
then
echo "Usage: $0"
exit 1
fi
# Use variable setting or default
: ${CALFILE:=$HOME/.calfile}
# Create calendar file if non-existent; flag
# creation error
if [ ! -f "$CALFILE" ]
then
echo "Creating default $HOME/.calfile"
> $HOME/.calfile || { echo "$HOME/.calfile: \
cannot create" ; exit 1 ; }
fi
# Variable declaration/assignment
DATE= LINE= ENTRY= REPLY="yes"
PAGER=/bin/more CLEAR=/bin/clear
# Set trap to not allow interrupts
trap '$CLEAR; echo "\007Interrupt ignored - use \
menu to quit. Press <Return> to continue."; \
read TMP; $CLEAR' 2 3
# Check the date
checkdate() {
while true
do
# Prompt for date
echo "Enter date in mmdd[yy] format (default today):\c"
read DATE
case $DATE in
# Default - use todays date
"" ) DATE=`date +%m%d%y` break ;;
# Integer argument
[0-9]* )
LENGTH=`echo $DATE | wc -c | sed -e 's/^
//p'`
# Verify date length
case "$LENGTH" in
5 ) MO=`echo $DATE | cut -c1,2`
DA=`echo $DATE | cut -c3,4`
YR=`date +%y`
DATE=$MO$DA$YR
;;
7 ) MO=`echo $DATE | cut -c1,2`
DA=`echo $DATE | cut -c3,4`
YR=`echo $DATE | cut -c5,6`
;;
* ) echo "Invalid date format - try again"
continue
;;
esac
# Validate date/month
if [ "$DA" -gt 00 -a "$DA" -lt 32 ]
then
if [ "$MO" -gt 00 -a "$MO" -lt 13 ]
then
break
else
echo "$MO: invalid month format - try again"
fi
else
echo "$DA: invalid day format - try again"
fi
;;
# Invalid date given
* ) echo "$DATE: invalid format - try again" ;;
esac
done
}
# Change an entry
changeentry() {
# Find entry - put it in temp found file
grep $DATE $CALFILE | tr ',' '\012'>/tmp/.FOUND$$
# Return if no entry was found
if [ ! -s /tmp/.FOUND$$ ]
then
$CLEAR
echo "Entry for $DATE not found - press
<Return> to continue\c"
read TMP
return
fi
# Prompt again for change
while [ "$REPLY" != "" ]
do
echo "Change/Add to entry for <$DATE>?\c"
read REPLY
case $REPLY in
[yY]* | "" )
break ;;
[nN]* ) echo "Ok, aborting entry change"
return ;;
* ) echo "Invalid reply - try again." ;;
esac
done
# Edit the temporary found file
${EDITOR:-vi} /tmp/.FOUND$$
# Remove the specified original entry
grep -v $DATE $CALFILE > /tmp/.CHANGE$$
# Put back new change in record format.
# Add trailing \n
(cat /tmp/.FOUND$$ | tr '\012' ',' ; echo ) \
>>/tmp/.CHANGE$$
# Put back new file
cat /tmp/.CHANGE$$ > $CALFILE
# Clean up tmp files
rm -rf /tmp/.CHANGE$$ /tmp/.FOUND$$
}
# Add new calendar entry
addentry() {
$CLEAR
ENTRY="$DATE"
# For existent entry, just add more data
COUNT=`grep -c "^$DATE" $CALFILE`
if [ "$COUNT" -gt 0 ]
then
changeentry
return
fi
# Prompt for input
echo "Enter info for $DATE: (enter <Return> by
itself when finished)"
while true
do
echo "=>\c"
read LINE
if [ -n "$LINE" ]
then
ENTRY="$ENTRY,$LINE"
else
break
fi
done
# Append to calendar file
echo $ENTRY>>$CALFILE
# Sort the calendar file
sort -o $CALFILE $CALFILE
}
formatentry() {
$CLEAR
X=$IFS
IFS=","
BORDER="**********************************"
BORDER1="* *"
REPLY=yes
TFILE=$1
if [ -s "$TFILE" ]
then
# Open calendar file for reading, and
# format output
(cat $TFILE | while read ENTRY
do
echo "$BORDER\n$BORDER1"
set $ENTRY
echo " *\r* DATE: $1"
echo "$BORDER1"
shift
for i
do
echo " *\r* $i"
done
echo "$BORDER1"
done
echo "$BORDER"
) | $PAGER
else
echo "No entries found."
fi
IFS=$X
# Prompt to continue
until [ "$REPLY" = "" ]
do
echo "Enter <Return> to continue...\c"
read REPLY
done
}
# Find specific entry
findentry() {
$CLEAR
# Check for entry - put it in temp found file
grep "$DATE" $CALFILE >/tmp/.FOUND$$
# Format found entries
#TFILE=/tmp/.FOUND$$
formatentry /tmp/.FOUND$$
# Clean up temp files
rm -rf /tmp/.FOUND$$
}
# Remove specific entry
delentry() {
# Look for entry
grep "$DATE" $CALFILE >/tmp/.FOUND$$
# Return if not found
if [ ! -s /tmp/.FOUND$$ ]
then
$CLEAR
echo "Entry for $DATE not found - press
<Return> to continue\c"
read TMP
return
fi
# Prompt to delete
while [ "$REPLY" != "" ]
do
echo "Delete entry for <$DATE>?\c"
read REPLY
case $REPLY in
[yY]* | "" )
break ;;
[nN]* ) echo "ok, aborting delete"
return ;;
* ) echo "Invalid reply - try again." ;;
esac
done
# Merge changes - put them in temporary file
grep -v "$DATE" $CALFILE > /tmp/.DEL$$
# Put back new file
cat /tmp/.DEL$$ > $CALFILE
# Clean up tmp files
rm -rf /tmp/.DEL$$ /tmp/.FOUND$$
}
# Set menu selection prompt
PS3="Enter selection or <Return> for default menu:"
# Display menu
while true
do
$CLEAR
echo " *** CALENDAR PROGRAM *** \n\n"
echo " 1) Add calendar entry\n"
echo " 2) Delete calendar entry\n"
echo " 3) Change calendar entry\n"
echo " 4) Find calendar entry\n"
echo " 5) List all calendar entries\n"
echo " 6) List todays calendar entry\n"
echo " 7) Exit\n\n"
echo "$PS3\c"
read i
case $i in
"1") checkdate
addentry
$CLEAR ;;
"2") checkdate
delentry
$CLEAR ;;
"3") checkdate
changeentry
$CLEAR ;;
"4") checkdate
findentry
$CLEAR ;;
"5") formatentry $CALFILE
$CLEAR ;;
"6") DATE=`date +%m%d%y`
findentry
$CLEAR ;;
"7") # Clean up files
rm -rf /tmp/.FOUND$$ /tmp/.CHANGE$$
/tmp/.DEL$$
exit ;;
* ) echo "\n\nInvalid selection - press
<Return> to continue\c"
read TMP
$CLEAR
continue ;;
esac
done
|