[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Lecture 20 Notes



These are the Bourne Shell notes

-- 
Title: Math 481/581 Lecture 20: Bourne Shell Scripts

Math 481/581 Lecture 20: Bourne Shell Scripts

© 1998 by Mark Hays <hays@math.arizona.edu>. All rights reserved.


Today we'll delve into writing shell scripts using the Bourne Shell.


Tutorials


Other Useful Commands

See the manpages for the following commands for detailed usage info.

CommandFunction
[ ... ]See "test"
awkScripting language
basenameStrip leading dirs from filename
catPrint files to stdout
chmodChange file access permissions
cpCopy files
cutPrint parts of lines of files
datePrint current date to stdout
dirnamePrint leading dirs of filename
duShow disk usage in KB for dirs
echoPrint args on stdout
exprPerform basic arithmetic
falseReturn nonzero exit status
fgrepPrint lines of files containing string
findRecursive directory search
grepPrint lines of files matching regexp
headGet first N lines of file
lsList files in dirs
mkdirCreate directories
mvMove or rename files
rmRemove files
rmdirRemove empty directories
sedStream editor
sleepPause for a specified interval
sortSort lines in files
tacReverse lines in files
tailGet last N lines of file
teeSave copy of stdin to file
testTest file attributes, etc.
touchSet modification time of files
trTranslate characters
trueReturn zero exit status
uniqPrint unique lines of sorted files
wcPrint # of lines, words, chars in files


Useful Constructs

# Send stderr into the void
command 2>/dev/null

# Print third column of each line in file
awk '{ print $3 }' < file

# Print total of third column of file
awk '{ tot = tot + $3 } END { print tot }' < file

# If there are any positional args, treat
# them as filenames. Send the contents of
# all the files to "whatever". If there
# are no positional args, send stdin to
# "whatever".
#
cat $* | whatever

# Print second field of colon-delimited file
cut -d: -f2 file

# Print first 40 chars of each line
cut -c1-40 file

# Print message to stderr
echo "Owie!" 1>&2

# Increment a variable
i = `expr $i + 1`

# Print paths of all .c files in and below CWD
find . -name '*.c' -print

# Remove all .dvi files in and below CWD
find . -name '*.dvi' -exec rm {} \;

# Print names of all .tex files in and below CWD
# containing "lemma"
find . -name '*.tex' -exec fgrep -l lemma {} \;

# Print all lines of file starting with a series of digits
grep '^[0-9][0-9]*' file

# Print first 20 lines of file
head -20 file

# Change all occurrences of "foo" to "bar"
sed -e 's/foo/bar/g' < file > newfile

# Print last 20 lines of file
tail -20 file

# If file is being written to by another process,
# this will show you the updates as they occur
tail -f file

# Squash uppercase to lowercase
tr '[A-Z]' '[a-z]' file > lcfile

# Squash multiple spaces to a single space
tr -s ' ' file > newfile

# Print number of lines in file
wc -l diss.tex


Example Shell Script

#!/bin/sh
#
# run -- runs commands with optional logging and timing
#

# function: issue help message and exit
usage()
{
cat << _EOF_
usage: `basename $0` [-a] [-q] [-s] [-fg] [-log logfile] [-c] command
	-q   runs quietly
	-fg  runs job in foreground
	-a   append to logfile
	-s   include date and timing info in logfile
	-log logs to the specified file
	-c   command follows

this script runs commands with optional logging and timing
_EOF_
exit 1;
}

# set defaults for switches
APPEND=0;	# append to logfile?
BG=1;		# run in background?
LOGFILE="";	# path of logfile
QUIET=0;	# run quietly?
STAMP=0;	# include timestamps info?

### process arguments
# no args -> help
[ $# -ne 0 ] || usage;

# got args -- process them
while [ $# -gt 0 ]; do
  case $1 in
     -h) usage;;
     -c) break;;
     -q) shift; QUIET=1;;
    -fg) shift; BG=0;;
   -log) shift; LOGFILE=$1; shift || usage;;
     -a) shift; APPEND=1;;
     -s) shift; STAMP=1;;
      *) break;;
  esac;
done
# no remaining args = no command = bail
[ $# -gt 0 ] || exit 1;

# figure out output redirection
LOGREDIR="";
if [ x"$LOGFILE" != x ]; then
	# logging to file...
	if [ $QUIET -ne 0 ]; then
		LOGREDIR=">>$LOGFILE 2>&1";
	else
		LOGREDIR="2>&1 | tee -a $LOGFILE";
	fi
	# redirection for timing info
	TIMEREDIR=$LOGREDIR
else
	# not logging to file -- send to bit bucket if quiet
	if [ $QUIET -ne 0 ]; then
		LOGREDIR=">/dev/null 2>&1";
	fi;
	# redirection for timing info
	TIMEREDIR=""
fi

# remove log file if we aren't appending
[ $APPEND -eq 0 ] && [ x"$LOGFILE" != x ] && /bin/rm -f $LOGFILE;

# construct command to execute
if [ $STAMP -ne 0 ]; then
	# include timestamp -- run in subshell
	CMD="( $*; date ) $LOGREDIR"
else
	# no timestamp -- just run it
	CMD="$* $LOGREDIR"
fi
[ $BG -eq 0 ] || CMD="$CMD &"

# output starting timestamp if requested
if [ $STAMP -ne 0 ]; then
	eval echo '================================================' $TIMEREDIR
	eval date $TIMEREDIR
	eval echo "`basename $0`: $*" $TIMEREDIR
fi

# execute command (and emit ending timestamp if requested)
eval $CMD

# success
exit 0

# EOF run