Test
test
is more frequently called as [
. [
is a symbolic link to test
$ type [
[ is a shell builtin
$ which [
/usr/bin/[
$ ls -l /usr/bin/[
lrwxrwxrwx 1 root root 4 Mar 27 2000 /usr/bin/[ -> test
$ ls -l /usr/bin/test
-rwxr-xr-x 1 root root 35368 Mar 27 2000 /usr/bin/test
This means that '[
' is actually a program, just like ls
and other programs, so it must be surrounded by spaces:
Test is a simple but powerful comparison utility. For full details, run man test
on your system
Test is most often invoked indirectly via the if
and while
statements.
The syntax for if...then...else...
is:
if [ ... ]
then
# if-code
else
# else-code
fi
Note: that fi
is if
backwards! This is used again later with case
and esac
.
Also, be aware of the syntax - the "if [ ... ]
" and the "then
" commands must be on different lines. Alternatively, the semicolon ";
" can separate them:
if [ ... ]; then
# do something
fi
You can also use the elif
, like this:
if [ something ]; then
echo "Something"
elif [ something_else ]; then
echo "Something else"
else
echo "None of the above"
fi
#!/bin/sh
if [ "$X" -lt "0" ]
then
echo "X is less than zero"
fi
if [ "$X" -gt "0" ]; then
echo "X is more than zero"
fi
[ "$X" -le "0" ] && \
echo "X is less than or equal to zero"
[ "$X" -ge "0" ] && \
echo "X is more than or equal to zero"
[ "$X" = "0" ] && \
echo "X is the string or number \"0\""
[ "$X" = "hello" ] && \
echo "X matches the string \"hello\""
[ "$X" != "hello" ] && \
echo "X is not the string \"hello\""
[ -n "$X" ] && \
echo "X is of nonzero length"
[ -f "$X" ] && \
echo "X is the path of a real file" || \
echo "No such file: $X"
[ -x "$X" ] && \
echo "X is the path of an executable file"
[ "$X" -nt "/etc/passwd" ] && \
echo "X is a file which is newer than /etc/passwd"
Note: that we can use the semicolon (;
) to join two lines together. This is often done to save a bit of space in simple if
statements.
The backslash (\
) serves a similar, but opposite purpose: it tells the shell that this is not the end of the line, but that the following line should be treated as part of the current line. This is useful for readability. It is customary to indent the following line after a backslash (\
) or semicolon (;
).
For example, the semicolon (;
) is often used like this to join the if
and then
keywords:
if [ "$X" -nt "/etc/passwd" ]; then
echo "X is a file which is newer than /etc/passwd"
fi
whilst the backslash (\
) is used to split the single-line command across two lines in the shell script file, for readability purposes:
[ "$X" -nt "/etc/passwd" ] && \
echo "X is a file which is newer than /etc/passwd"
test
can perform many tests on numbers, strings, and filenames. -a
, -e
(both meaning "file exists"), -S
(file is a Socket), -nt
(file is newer than), -ot
(file is older than), -ef
(paths refer to the same file) and -O
(file is owned by the user running the test)
There is a simpler way of writing if
statements: The &&
and ||
commands give code to run if the result is true, or false, respectively.
#!/bin/sh
[ $X -ne 0 ] && echo "X isn't zero" || echo "X is zero"
[ -f $X ] && echo "X is a file" || echo "X is not a file"
[ -n $X ] && echo "X is of non-zero length" || \
echo "X is of zero length"
The if...then...else...
structure is much more readable. Use of the [...]
construct is recommended for while loops
echo -en "Please guess the magic number: "
read X
echo $X | grep "[^0-9]" > /dev/null 2>&1
if [ "$?" -eq "0" ]; then
# If the grep found something other than 0-9
# then it's not an integer.
echo "Sorry, wanted a number"
else
# The grep found only 0-9, so it's an integer.
# We can safely do a test on it.
if [ "$X" -eq "7" ]; then
echo "You entered the magic number!"
fi
fi
The >/dev/null 2>&1
directs any output or errors to the special "null" device, instead of going to the user's screen. We can use test in while loops as follows:
#!/bin/sh
X=0
while [ -n "$X" ]
do
echo "Enter some text (RETURN to quit)"
read X
echo "You said: $X"
done
This code will keep asking for input until you hit RETURN (X is zero length)
Case:
The case
statement saves going through a whole set of if .. then .. else
statements. Its syntax is really quite simple:
#!/bin/sh
echo "Please talk to me ..."
while :
do
read INPUT_STRING
case $INPUT_STRING in
hello)
echo "Hello yourself!"
;;
bye)
echo "See you again!"
break
;;
*)
echo "Sorry, I don't understand"
;;
esac
done
echo
echo "That's all folks!"
The options we understand are then listed and followed by a right bracket, as hello)
and bye)
.
This means that if INPUT_STRING
matches hello
then that section of code is executed, up to the double semicolon.
Note: that if we wanted to exit the script completely then we would use the command exit
instead of break
.
The third option here, the *)
, is the default catch-all condition; it is not required, but is often useful for debugging purposes
The whole case statement is ended with esac
(case backwards!) then we end the while loop with a done
.
Last updated
Was this helpful?