CS 279 - Week 8 Lab - 10-10-12
* both test and [ ] can contain a variety of
tests (those listed in the link on the
public course web page, for example)
...you can play with test from the command line,
BUT using it with && (short-circuiting boolean
and) and an echo can let you see if the test
succeeded -- only if it succeeded will the
echo be evaluated:
test -e pig.txt && echo 'you have that file'
...you'll only see
you have that file
...IF pig.txt exists;
-e file - true if file exists
-f file - true if regular file
-d file - true if file is a directory
-h file - true if file is a symbolic link
-r file - true if file is readable by you
-w file - ...is writable by you
-x file - ...is executable by you
-s file - ...exists and is not empty
* you can use ! in front of one of these
to test for its negation --
test ! -e pig.txt && echo 'file does not exist'
NOTE:
* you can EXIT a bash shell script with a particular
exit status by using the exit command followed
by the desired integer exit status
if [ ! -e $desired_file ]
then
echo "$0: $desired_file does not exist"
echo " ...exiting"
exit 1
fi
* if you are exiting "prematurely", it is good
style to use a non-zero exit status
(and that's now a class coding standard, too)
* example using exit: exit-ex.sh
* you can see if a string is empty (length of 0) or not
-z string - true if the string is empty (length
of 0)
-n string - true if the string is not empty
(nonzero length)
* some binary/more comparative testers: (still
in [ ] or with test)
file1 -nt file2 - true if file1 is newer than
file2
file1 -ot file2 - true if file1 is older than
file2
string1 = string2 - true if string1 is identical
to string2
string != string2 - true if string1 is NOT
identical to string2
* BEWARE - be prepared for spaces in filenames!
advice from:
http://www.davidpashley.com/articles/writing-robust-shell-scripts.html
if [ $filename = "foo" ]
...will FAIL if $filename contains a space
if [ "$filename" = "foo" ]
...WON'T fail if $filename contains a space
* this is also of concern when you are grabbing
all of the command-line arguments in a shell
script:
for i in $@
do
echo $i
done
...say this is in a script for-quotes.sh --
if you call it with:
for-quotes.sh moo "arf oink"
...you'll get THREE lines of output:
moo
arf
oink
...NOT the two you probably expected:
moo
arf oink
* the blank in the second command line argument is making it
look like multiple arguments;
* this won't happen if you double-quote the $@:
for i in "$@"
do
echo $i
done
...now, you'll get the desired 1-line of output for each
command-line argument, even if one happens to contain blanks
...for-quotes.sh now has BOTH of the above loops, so you
can compare and contrast their behavior
* there are also tests for comparing integers
int1 -eq int2 --- true if int1 is identical to
int2
int1 -ne int2 ...not identical
int1 -lt int2 ...less than
int1 -gt int2 ...greater than
int1 -le int2 ...less than or equal
int1 -ge int2 ...greater than or equal
* more-than-5.sh shows an example of using one of the
above to see if the number of command-line arguments
(obtainable using $#) is acceptable for that shell script;
* talking a little more about operators that
work inside [[ ]]
string =~ regex true if string matches
regex
* remember NOT to put quotes around
the regex!
* note that && and || are short-circuited boolean-and and
boolean-or operators (respectively) inside [[ ]]
* string = filename-expansion-pattern
string == filename-expansion-pattern
(notice, this is different than = in [ ] )
* glob-play.sh tries this out;
* can use ( ) to change evaluation
precedence in [[ ]], too;
* OH -- and what if you'd like to loop through all of the
lines in a particular file?
...there's more than one way, BUT this way DOES
maintain one-line-per-loop-iteration behavior
(even if a line contains blanks):
while read line
do
echo "\$line: $line"
done < fodder.txt
notice the
read
...as part of the while condition, and the
< filename
AFTER the while loop's done !
done < filename
* read-lines-ex.sh shows this in action