The test, [, and [[ commands

The test builtin command is used to evaluate conditional expressions; it tests whether two strings are equal, whether a file exists, whether a string is empty, and other functions. The complete list of tests is available with help test.

For example, to test whether a file exists, you might use the following:

$ test -e /etc/passwd && echo 'Password file exists!'
Password file exists!

There is an alternative way to write this command, called [. No, that's not a typo; [ is the name of the command! We can see this with type; there's even a program on our filesystem by the same name:

bash$ type -a [
[ is a shell builtin
[ is /usr/bin/[

The primary difference between test and [ is that [ requires its last argument to be ]. The result is that it looks like a pair of square brackets surrounding the condition:

$ [ -e /etc/passwd ] && echo 'Password file exists!'

Because this syntax is confusing and can be hard to understand, Bash implements a new version of [ called [[. It's actually not really a command; again, type can tell us the whole truth:

bash$ type [[
[[ is a shell keyword

In Bash scripts, you are not likely to need test very much, if ever, but you will definitely need the [[ keyword that in turn derives its syntax from the [ command. Understanding the test and [ commands and the unique way conditionals work in shell clarifies one of the most confusing parts of shell script behavior. We'll look at that in more detail in Chapter 7, Scripts, Functions, and Aliases.