Welcome!

Linux Authors: Reuven Cohen, Michael Sheehan, Lavenya Dilip, Ian Thain, Bruce Armstrong

Related Topics: Linux

Linux: Article

Everything You Wanted to Know About the Test Command

The basics

In the October issue of LWM (Vol. 2, issue 10) I explored the basic logic of conditional execution sequences on the command line, differentiating between "&&" and "||". If you didn't read it, I encourage you to check it out at http://linux.intuitive.com/, along with all the other back columns of Wicked Cool Linux.

In addition, I briefly explored how you can use parentheses to group a sequence of commands into a logical block and then have that block be part of a conditional execution sequence:


(grep dialup /var/log/modem | \
      mail -s dialup taylor) || echo failed

This time I want to delve into one of the cornerstones of shell scripting, a command that not only often hides as a punctuation character, but is rarely utilized to its full capabilities: test.

The Basics of the Test Command

The best place to start learning about the test command is to check out the man page associated with it. You'll be amazed at just how many different conditional tests it supports. Try man test on your system to see what I mean.

"But I've read lots of shell scripts and have never seen 'test' referenced?" you may be thinking. That's because test usually masquerades as "[":


$ ls -l /bin/{test,[}
-r-xr-xr-x  1 root  wheel  18288 14 Jun 01:16 /bin/[
-r-xr-xr-x  1 root  wheel  18288 14 Jun 01:16 /bin/test

(Notice the useful Bash grouping notation there too, with x/{a,b} expanding to x/a and x/b. A helpful shortcut!)

The test command - in either guise - is used most commonly with a conditional if statement, which takes the form:


	if condition 
	then
	  command block
	f i

Typically, scripters insert a semicolon between the condition and the "then" so that it's three lines, not four. Here's a very common simple condition, utilizing the -e test that returns true (zero) if the specified file exists and false (non-zero) if it doesn't:


	if [ -e "myfile" ] ; then
	  echo myfile exists
	f i

Notice that if you use the "[" shortcut to test, you are required to include the closing "]", which is good form anyway. However, if you wanted to call test directly, the following is 100% identical in its result:


if test -e "myfile" ; then

Notice the use of spaces in the if statements above. Whether you use "[" or "test", you'll find that omitting needed spaces around the elements of the conditional will cause scary and confusing error messages, so don't try to be too succinct in your scripts.

Understanding Return Codes

Before going any further, it's worth a brief sidetrack to explain how Unix commands communicate success or failure: through a numeric return code that is defined to be zero on success, non-zero and a meaningful error code value on failure. You can see this when you look at the test man page and it shows:


RETURN VALUES
     The test utility exits with one of the following values:
         0       expression evaluated to true.
         1       expression evaluated to false or expression was missing.
        >1      An error occurred.

This return code is exactly what the shell uses when it evaluates conditionals within an if statement, hence the existence of the two oddly named true and false commands: they return 0 or non-zero, respectively, and are used in conditional statements. The following is not only legal but it'll work just fine in Unix:


	if true ; then
	  echo true is true, yowza
	else
	  echo how odd. true is false
	f i

(This time notice that I slipped in an else clause.)

Let's go back to the test statement, though, now that you can see how the shell implements conditional statement blocks.

Tests on Files

There are lots of different tests that can be performed with the test command, so let's start by just looking at the most common file-related conditions in Table 1.

With that knowledge, and the addition that "!" negates (flips) the logic of any given conditional expression, the following snippet of script should make sense to you:


if [ ! -e $file ] ; then
  echo "$file doesn't exist"
f i
if [ -d $file ] ; then
  echo "$file is a directory"
f i
if [ -f $file ] ; then
  echo "$file is a file"
f i

There's oh so much more you can do with conditionals, especially as we continue to explore the many looping and flow-control mechanisms in the shell, but let's stop here and wait until next month to delve into this any further.

More Stories By Dave Taylor

Dave Taylor, a contributing editor to Linux.SYS-CON.com, has been involved with the Linux and Unix community since 1980 and has written a number of best-selling Unix books. Currently, he writes, teaches, and works as a management consultant to tech startups, along with his new venture, Ask Dave Taylor!, www.askdavetaylor.com and his personal blog is www.blog.Linux.SYS-CON.com. To contact Dave, please go to /www.intuitive.com/contact.shtml.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.