These are the Bourne Shell notes --Title: Math 481/581 Lecture 20: Bourne Shell Scripts
Today we'll delve into writing shell scripts using the Bourne Shell.
| Command | Function |
|---|---|
| [ ... ] | See "test" |
| awk | Scripting language |
| basename | Strip leading dirs from filename |
| cat | Print files to stdout |
| chmod | Change file access permissions |
| cp | Copy files |
| cut | Print parts of lines of files |
| date | Print current date to stdout |
| dirname | Print leading dirs of filename |
| du | Show disk usage in KB for dirs |
| echo | Print args on stdout |
| expr | Perform basic arithmetic |
| false | Return nonzero exit status |
| fgrep | Print lines of files containing string |
| find | Recursive directory search |
| grep | Print lines of files matching regexp |
| head | Get first N lines of file |
| ls | List files in dirs |
| mkdir | Create directories |
| mv | Move or rename files |
| rm | Remove files |
| rmdir | Remove empty directories |
| sed | Stream editor |
| sleep | Pause for a specified interval |
| sort | Sort lines in files |
| tac | Reverse lines in files |
| tail | Get last N lines of file |
| tee | Save copy of stdin to file |
| test | Test file attributes, etc. |
| touch | Set modification time of files |
| tr | Translate characters |
| true | Return zero exit status |
| uniq | Print unique lines of sorted files |
| wc | Print # of lines, words, chars in files |
# 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
#!/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