The 'test' statement
The command to accomplish this is test . Followed by
arguments, test will give an exit status of 0 if the
arguments evaluate to True. There are two ways of invoking
test :
test arguments
[ arguments ]
and we shall use the latter for the rest of this book. To give
you the flavour, the following checks whether file
testfile exists and displays a suitable message if it
does:
$ [ -e testfile ] && echo Testfile
exists
Using the alternative syntax this would look like:
$ test -e testfile && echo Testfile
exists
The operator -e , when presented as an
argument to test , examines the following argument and,
if that file exists, the command succeeds (exit status 0),
otherwise it fails with exit status 1. Various options are
available to test .
Worked example
Write a script which will read in the name of a file and print
out a message indicating whether or not it is a directory.
Solution: Use test with option
-d to check the file, and || and
&& to control which message is output.
echo Input a file name: # Prompt the user ...
read FILENAME # input a file name ...
([ -d $FILENAME ] && # check it's a directory ...
# then confirm this if so
echo $FILENAME is a directory) ||
echo $FILENAME is not a directory
A regular file is essentially one that is not a directory; there
are other sorts of non-regular files, such as FIFO
files, but they do not concern us here.
For instance, to check whether variable NAME has
been set a value that is not the null string, we might have:
$ [ "$NAME" ] || echo NAME is
unset
Note that we have enclosed $ NAME in double quotes;
test expects to get an argument, and if we did not
enclose it in quotes, and NAME was unset (or contained
only whitespace), the line would become
[ ] || echo NAME is unset
prior to execution, which would give an error, whereas
[ "" ] || echo NAME is unset
would be OK.
Worked example
Write a script to greet the person running it if they are logged
on as user chris .
Solution: Use logname to check the
user's name (not the variable LOGNAME , which might
accidentally have been changed), and test to compare
it with chris .
[ "$( logname )" = chris ] && echo Hello
Chris
The numerical checks listed that test can perform
are the principal way of doing numerical comparisons using the
shell. They only work with whole numbers, however, and if you wish
to perform complex tasks using floating-point numbers you are
advised to use bc . As an example, we code the solution
to the question posed at the start of this section, which was: 'If
file A is smaller than 100 lines then display it on
the terminal, otherwise tell me that it's bigger than 100
lines.'
FILESIZE=$( wc -l A ) # Use wc -l to count the lines
([ "$FILESIZE" -gt 100 ] && echo File too big) || cat A
There is a difference between the operators = and
-eq For instance,
[ 0 -eq 00 ]
succeeds, as 0 and 00 are numerically
equal, but
[ 0 = 00 ]
fails, as they are different strings of characters.
Worked example
Write a script to request you to type in a number, and then to
guess its square; it should then either congratulate you or tell
you the correct answer.
Solution: After reading in a number into variable
NUMBER , construct an expression
$NUMBER * $NUMBER to be piped to
bc , assigning the output of the calculation to
SQUARE . Then, after reading in the user's guess into
variable GUESS , use test to check whether
GUESS and SQUARE are the same.
Notice the different 'style' of comments used here - each on a
line of its own; this style is preferred with long command
lines.
# Prompt the user and read in the number
echo Type in a number:
read NUMBER
# Evaluate the square of the number using bc
SQUARE=$( echo "$NUMBER * $NUMBER" | bc )
# Prompt the user and read in the guessed answer
echo Guess its square:
read GUESS
# If the guess is equal to the square, confirm ...
([ "$GUESS" -eq "$SQUARE" ] && echo Correct) ||
# otherwise display the correct answer
echo The correct answer is $SQUARE
Since test requires arguments, you must separate
those arguments from the word test by whitespace.
Similarly, if you are using the square bracket notation for
test , you should separate the square brackets from
what is inside the brackets. Otherwise, the brackets themselves
would become part of the strings which they should enclose. For
instance,
[ hello = hello]
would attempt to compare string hello with string
hello] and think that you had forgotten to provide the
closing square bracket.
|