#!/bin/sh
VERSION=0.2.4 # version of this script
PATH=/bin/:/usr/bin # set a safe path
LOCK=/tmp/blah_lock.$$ # $$ is the PID of the shell
touch $LOCK # create a 'lock'
#-----------------------------------------------------------------------------
# This subroutine prints to standard output (cat -) everything until 'EOF' is
# found. It also removes the 'lock' file and exits with a return code of 1.
# The purpose of this subroutine is simply to describe the program to the
# person running it, and to show a synopsis and example of how to use it.
#
usage()
{
cat - << EOF
This program does nothing functionally useful; however, its source code
is an example of a number of sh programming constructs.
usage: $0 [-h|--help] [--version] [-vd] [-n num] word file
example: $0 alex /etc/group
EOF
rm -f $LOCK
exit 1
}
#-----------------------------------------------------------------------------
# This subroutine will prompt the operator whether to continue. If something
# other then 'y' or 'Y' is entered, the program exits, making the "default"
# entry result in an exit. Therefore if the operator presses Enter, the
# program will exit (the 'N' is capitalized to indicate this default
# behaviour). If 'y' or 'Y' is pressed, the program prints a statement and
# continues execution.
#
ask_to_continue()
{
echo -n "Do you want to continue ? [y|N] "
read CONTINUE
if [ "x${CONTINUE}" != "xy" ] && [ "x${CONTINUE}" != "xY" ] ; then
echo "You chose to abort." ; rm -f $LOCK ; exit 1
else
echo "Continuing..."
fi
}
#-----------------------------------------------------------------------------
# This subroutine will prompt the operator to continue execution. If something
# other then 'n' or 'y' is entered, the program continues to prompt the user
# until one of the two keys is entered. If 'n' is entered, the program exits.
# If 'y' is entered, the program prints a statement and continues execution.
#
ask_to_continue_2()
{
echo -n "Do you want to continue ? [y|n] "
read CONTINUE
if [ "x${CONTINUE}" != "xy" ] && [ "x${CONTINUE}" != "xn" ] ; then
echo "You have made an incorrect entry; next time enter 'y' or 'n'."
ask_to_continue_2
elif [ "x${CONTINUE}" = "xn" ] ; then
echo "You chose to abort."
rm -f $LOCK
exit 1
else
echo "Continuing..."
fi
}
#-----------------------------------------------------------------------------
#
# Process the command line options (manually, without the getopts command).
#
# Study this method and the one below, and you will see that this method is
# not as easy and reliable as the one below (despite its shortness)...
# that's why I've commented it out.
#
#while [ $# != 0 ] ; do
# case $1 in
# '-h') usage;;
# '-v') VERBOSE=1; echo "VERBOSE mode is ON" ;;
# '-d') DEBUG=1; echo "DEBUG mode is ON" ;;
# '-n') NUMBER=$2; echo "NUMBER is $NUMBER"; shift ;;
# '--version') echo "Version $VERSION" ;;
# '--help') usage ;;
# * ) break ;;
# esac
# shift
#done
#-----------------------------------------------------------------------------
#
# Process the command line options (using getopts).
#
# The internal getopts command takes two parameters: a series of letters
# representing options to expect, and a variable name which is set to the
# parsed option on each call to getopts. To indicate that an option takes
# an argument it should be followed by a colon. A hypen is also allowed
# as a possible option.
#
# At each call to getopts, the index of the next argument is placed into the
# shell variable OPTIND. When an option that takes an argument is parsed,
# the next positional parameter is assumed to be its argument, and is placed
# into the shell variable OPTARG.
#
# In the code below, when an option is parsed, $opt is set to that option.
# So if '-v' is parsed, $opt evaluates to 'v'. The case command will match
# the 'v' and execute everything until ';;' is encountered.
#
# The way the hyphen is used below, it allows options such as '--version'.
#
# After the while loop has completed, it is important to execute the shift
# command as it is written below. It does positional parameter shuffling
# which allows the program to continue as expected by moving (shifting) the
# options out of the way, so that the command line arguments can be processed.
#
while getopts "hvdn:-:" opt ; do
case $opt in
h ) usage ;;
v ) VERBOSE=1; echo "VERBOSE mode is ON" ;;
d ) DEBUG=1; echo "DEBUG mode is ON" ;;
n ) NUMBER=$OPTARG; echo "NUMBER is $NUMBER" ;;
- ) case $OPTARG in
version ) echo "Version $VERSION" ;;
help ) usage ;;
* ) echo "An unexpected double-hyphen option was encountered."
echo; usage ;;
esac ;;
? ) echo "An invalid option was encountered."; echo; usage ;;
* ) echo "An unexpected error occured."; echo; usage ;;
esac
done
# Use the second shift instead of the first if you have an old version of sh.
shift $(($OPTIND -1))
#shift `expr $OPTIND - 1`
#-----------------------------------------------------------------------------
#
# Check the number of command line arguments.
#
if [ $# != 2 ] ; then
echo "You've passed $# command line argument(s), while 2 are expected."
usage
fi
#-----------------------------------------------------------------------------
#
# Display the arguments passed via the command line.
#
echo "Argument 1: $1"
echo "Argument 2: $2"
#-----------------------------------------------------------------------------
#
# A good example of how to prompt the operator whether to continue.
#
ask_to_continue
#
# Another example of how to prompt to continue; however this one is less
# friendly because it does not assume a default, and it is too persistent.
#
ask_to_continue_2
#-----------------------------------------------------------------------------
#
# An example of grouping commands together...
# execute two separate echo commands and redirect the output of both to a file
#
{ echo -n "Hello, "; echo " World!"; } > $LOCK
{ echo "Appending a second line to the file."; } >> $LOCK
{ echo "Appending a third line to the file."; } >> $LOCK
#-----------------------------------------------------------------------------
#
# Check the number of lines in the file.
#
# In this case, the file name is the value of the variable $LOCK.
#
if [ -r $LOCK ] ; then
LINES=`wc -l $LOCK | awk '{print $1}'`
if [ "x${LINES}" = "x1" ] ; then
echo "The file named $LOCK contains ( 1 ) line."
else
echo "The file named $LOCK contains ( $LINES ) lines."
fi
fi
#-----------------------------------------------------------------------------
# Generate a list of files, and redirect that list into a file.
# Ask the operator to enter a file name. Check the entry for semi-validity.
# Compare the entered file name to the list of files in the current directory.
#
if [ -w $LOCK ] ; then
#
# Send a list of all files (one per line) in the current directory,
# into the file named by the variable $LOCK.
#
ls -F . > $LOCK
#
# Prompt for a file name.
#
echo -n "Type the name of a file to create: "
read NEWFILE
#
# Check validity of entry.
# (Doesn't check for embedded spaces or potentially dangerous characters).
#
if [ -z $NEWFILE ] || [ ! -n $NEWFILE ] ; then
echo "A file name must contain at least one non-space character."
echo "Next time type something valid."
rm -f $LOCK
exit 2
fi
#
# Run through the list of filenames, ignoring files starting with a period.
#
for FILENAME in `sed 's/^\..*$//' $LOCK | uniq` ; do
if [ $DEBUG ] ; then
echo "file: $FILENAME"
fi
if [ "x${FILENAME}" = "x${NEWFILE}" ] ; then
echo -n "Sorry, $NEWFILE already exists."
rm -f $LOCK
exit 2
fi
done
echo "The file name you entered is unique: $NEWFILE"
fi
#-----------------------------------------------------------------------------
# An example of code that relies on perl to create a list of numbers
# which are then used by a 'for' loop to echo some text. In a practical
# sense, the echo would be removed, resulting in the creation of a number
# of symbolic links.
#
for i in `perl -e '$i=0; print $i++ . " " while( $i<11 )'` ; do
echo ln -s /home/u${i} /u${i}
done
#-----------------------------------------------------------------------------
echo "All done."
rm -f $LOCK
syntax highlighted by Code2HTML, v. 0.9.1