Friday, May 16, 2008

Linux tip: Bash test and comparison functions

test and [

The test builtin command returns 0 (True) or 1 (False), depending on the evaluation of an expression, expr. You can also use square brackets: test expr and [ expr ] are equivalent. You can examine the return value by displaying $?; you can use the return value with && and ||; or you can test it using the various conditional constructs that are covered later in this tip.


Listing 1. Some simple tests
              
[ian@pinguino ~]$ test 3 -gt 4 && echo True || echo false
false
[ian@pinguino ~]$ [ "abc" != "def" ];echo $?
0
[ian@pinguino ~]$ test -d "$HOME" ;echo $?
0

In the first example in Listing 1, the -gt operator performs an arithmetic comparison between two literal values. In the second example, the alternate [ ] form compares two strings for inequality. In the final example, the value of the HOME variable is tested to see if it is a directory using the -d unary operator.

You can compare arithmetic values using one of -eq, -ne, -lt, -le, -gt, or -ge, meaning equal, not equal, less than, less than or equal, greater than, and greater than or equal, respectively.

You can compare strings for equality, inequality, or whether the first string sorts before or after the second one using the operators =, !=, <, and >, respectively. The unary operator -z tests for a null string, while -n or no operator at all returns True if a string is not empty.

Note: the < and > operators are also used by the shell for redirection, so you must escape them using \< or \>. Listing 2 shows more examples of string tests. Check that they are as you expect.


Listing 2. Some string tests
              
[ian@pinguino ~]$ test "abc" = "def" ;echo $?
1
[ian@pinguino ~]$ [ "abc" != "def" ];echo $?
0
[ian@pinguino ~]$ [ "abc" \< "def" ];echo $? 0 [ian@pinguino ~]$ [ "abc" \> "def" ];echo $?
1
[ian@pinguino ~]$ [ "abc" \<"abc" ];echo $? 1 [ian@pinguino ~]$ [ "abc" \> "abc" ];echo $?
1

Some of the more common file tests are shown in Table 1. The result is True if the file tested is a file that exists and that has the specified characteristic.

Table 1. Some common file tests
OperatorCharacteristic
-dDirectory
-eExists (also -a)
-fRegular file
-hSymbolic link (also -L)
-pNamed pipe
-rReadable by you
-sNot empty
-SSocket
-wWritable by you
-NHas been modified since last being read

In addition to the unary tests above, you can compare two files with the binary operators shown in Table 2.

Table 2. Testing pairs of files
OperatorTrue if
-ntTest if file1 is newer than file 2. The modification date is used for this and the next comparison.
-otTest if file1 is older than file 2.
-efTest if file1 is a hard link to file2.

No comments: