CS/CE 218 Lecture -*-Outline-*- Connection: already seen single statements in shell programming now to look at more complex programs, using compound statements. * statements of the Bourne shell ** testing success (exit value)pages 467-471 each command execution can be tested for success or failure (error) Q: How do you know if a Unix command is successful? returns 0 exit code should return >0 if unsuccessful Q: How do you control the exit code of a shell script? this is the most common mistake of novice Unix programmers: incorrect return code makes success of command difficult to tell unfortuanately, book routinely makes this mistake (its semantics are hard to get right) *** test command (pages 471-478) Q: what kinds of things can "test" test? numeric values (-eq) file types character strings (=) --------------- if test $# -eq 0 then echo "$USAGE" >&2 exit 1 fi --------------- Q: How do you test to see if a file is readable? test -r file Another syntax for test is [ -r file ] usually best to enclose arguments to test in double quotes, in case user called it wrong if test "$1" = '-?' then ... fi *** if statement and if-then-else Q: If you think of true as 1, how does "if" act strangely? recall dviprint example... --------------- RET=0 if dvialw -q $f then lpr -P${PRINTER-lw1} \#${f}-alw else RET=1 fi exit $RET --------------- different syntax in cshell *** && and || combinations --------------- # almost equivalent RET=0 dvialw -q $f && lpr -P${PRINTER-lw1} \#${f}-alw || RET=1 exit $RET --------------- the RET=1 is done if *either* fails *** while and until loops ------------------ while true # poke $owcpid every so often do sleep "$sleepytime" kill -IO "$owcpid" || exit done > /dev/null 2>&1 ------------------ note, you can redirect output from a loop as a whole ** for loops (section 13.6) Q: Do you know in advance how many times a for loop will execute? different syntax in cshell ------------------ for f do dvialw -q $f && lpr -P${PRINTER-lw1} \#${f}-alw || RET=1 done ------------------ this is for all command line arguments can also do for f in * ** break and continue statements (page 481) often have a "last option" -- or - Q: What does the following do? ------------------ while test -n "$1" do case "$1" in -[bB]) base_option=TRUE shift;; --) shift break;; *) break ;; esac done ------------------ Q: How is "continue" like a goto? ** case statement (page 484-485) pattern matching on strings (not numeric as in Pascal) uses shell meta characters can also use | to mean "or" case "$1" in -b|-B) ... ;; ... esac Q: Do you understand the following command's details? --------------------- # eclean -- clean up emacs backup files # # SYNOPSIS: Remove files whose names match *~ from current working directory # Giving prefixes causes only files with names starting in that list # to be removed. # # AUTHOR: Gary T. Leavens USAGE='Usage: '"$0"' [prefix ...]' case "$1" in -*) echo "$USAGE" >&2 exit 2 ;; esac # all files if no prefix specified if test $# = 0 then set '*' fi # remove the files for p do rm -f ${p}~ done exit 0 --------------------- Why is it set '*' above instead of set *?