20. Conditional Expressions

Conditional expression are evaluated by the tests command or within the "[ ... ]" or "[[ ... ]]" operators. Bash supports a many tests. True tests exists on 0, false on 1. To test the existence of a file:

$ > file
$ [ -a file ] && echo "file exists"

To test the existence of a block special file:

$ [ -b /dev/sda ] && echo "block special file exists"

To test the existence of a character special file:

$ [ -c /dev/tty ]  && echo "character special file exists"

To test the existence of a directory:

$ [ -d ~ ] && echo "directory exists"

To test the existence of a regular file:

$ [ -f file ] && echo "regular file exists"

To test that the set-group-id bit is set:

$ chmod g+s file 
$ [ -g file ] && echo "set-group-id bit set"

To test the existence of a symbolic link:

$ ln -s file slink
$ [ -h slink ] && echo "symbolic link exists"

To test that the sticky bit is set:

$ chmod +t file
$ [ -k file ] && echo "sticky bit set"

To test the existence of a named pipe:

$ mkfifo fifo
$ [ -p fifo ] && echo "fifo exists"

To test the existence that the file is readable:

$ [ -r file ] && echo "file is readable"

To test that the file is greater than 0 byte:

$ echo 1 >> file
$ [ -s file ] && echo "file size greater 0"

To test that the file descriptor is open and refers to a terminal:

$ exec 3<> /dev/tty
$ [ -t 3 ] && echo "open file descriptor refers to terminal" 

To test the existence that the set-userid-bit is set:

$ chmod u+s file
$ [ -u file ] && echo "set-userid-bit is set" 

To test that the file or directory is writable:

$ chmod u+w file
$ [ -w file ] && echo "file is writeable"

To test that the file or directory is executable:

$ chmod u+x file
$ [ -x file ] && echo "file is executeable"

To test that the file is owned by the effective group id:

$ [ -G file ] && echo "file owned by effective group id"

To test that the file was modified since the last read:

$ cat file && touch file
$ [ -N file ] && echo "modified since last read"

To test that the file is owned by the effective user id

$ [ -O file ] && echo "file owned by effective user id"

To test the existence of a socket:

$ exec 4<> /dev/udp/127.0.0.1/80
$ [ -S 4 ] && echo "socket exists"

To test that both files refer to the same device and inode:

$ [ file -ef file ] && echo "the two files refers to same device and inode"

To test that the first file exists and was modified after second file or exists only:

$ touch file2 && sleep 1 && touch file
$ [ file -nt file2 ] && echo "first newer than second file"

To test that the second file exists and was modified after first file or exists only (vice versa):

$ [ file2 -ot file ] && echo "first file older than second file"

To test that a option is set:

$ [ -o i ] && echo "shell is interactive"

To test that a variable is set:

$ [ -v HOME ] && echo "HOME variable has been assigned a value"

To test that the length of string is 0:

$ [ -z "" ] && echo "length is 0"

To test that the length of a string is not 0 (negation):

$ [ "eins" ] && echo "string not 0"

To test that two strings are equal:

$ [ "1" == "1" ] && echo "strings are equal"

To test that two strings are not equal (negation):

$ [ "0" != "1" ] && echo "strings are not equal"

To test that the first string sorts before the second string lexicographically:

$ [ "abc" < "def" ] && echo "first string sorts before second"

To test that the second string sorts before the first string lexicographically (vice versa):

$ [ "def" > "abc"] && echo "second string sorts before first"

To test that two integers are equal:

$ [ 1 -eq 1 ] && echo "integers are equal"

To test that two integers are not equal (vice versa):

$ [ 1 -ne 0 ] && echo "integers are not equal"

To test that the first integer is lower or equal than the second:

$ [ 0 -le  0 ] && echo "first integer is lower equal"

To test that the first integer is lower than the second:

 $ [ 0 -lt 1 ] && echo "first integer is lower"

To test that the first integer is greater than the second:

$ [ 1 -gt 0 ] && echo "first integer is greater"

To test that first integer is greater or equal than the second:

$ [ 1 -ge 1 ] && echo "first integer is greater equal"

For clarity: The following expressions compare two integers:

$ [ 1 -gt 0 ] && (( 1 > 0 )) && echo "comparing two integers"

and the next expressions compare two strings:

$ [ a > 0 ] && [[ (( a > 0 )) ]] && echo "this is a comparison of two strings"

The difference is made by the operators, not from the values! The following expression is always evaluated to true, because the return status of the arithmetic expansion is always true, even if the expanded string is evaluated to false:

$ [ $(( 0 > 1 )) ] && echo "always true, even if arithimetic expression is false"