Bash Conditional Expressions

Conditional Expressions are signals - also called primaries - that bash uses as a means of performing tests, using the info you provide.

Lets say you are wanting to copy over a file from one location to another, but don’t need to do this if the file already exists in the final location. This is one way to test for that!

if [[ ! -e /etc/foo ]]; then
  echo "Looks like /etc/foo doesn't exist"
fi

Breakdown

  1. [[ ]] So, the double brackets here are necessary for #!/bin/bash, of which, to be honest, using the double brackets as the standard setup seems to be what makes the most sense.

  2. ! The exclamation point is how you negate expressions through a lot of bash in general. So, here, its testing if /etc/foo exists.

  3. -e True if File Exists. Its a very broad testing flag.

  4. After the brackets are closed, you use ; to tell bash that your expression line is finished.

  5. Then, you do whatever you need to do.

  6. fi then, the fi is what tells bash that if is finished.

Conditional Expression Primaries

The following test flags go with:

if [[ -e /bin/bash ]]; then ...
  <some code>
elif [[ ! -e /bin/dash ]]; then
  <some code>
fi

Use [[ ]] with double == and use [ ] with =

The first line, -e /bin/bash is the positive side of the -e FILE test.

There are a LOT of ways to test things, using either if-then-else, case or while loops.

Test Expressions

Flag

Explainer

-a FILE

True if file exists

-b FILE

True if file exists and is a block special file

-c FILE

True if file exists and is a character special file

-d FILE

True if file exists and is a directory

-e FILE

True if file exists

-f FILE

True if file exists and is a regular file

-g FILE

True if file exists and its set-group-id bit is set

-G FILE

True if file exists and is owned by the effective group id

-h FILE

True if file exists and is a symbolic link

-k FILE

True if file exists and its sticky bit is set

-L FILE

True if file exists and is a symbolic link

-n STRING

True if the length of string is NON-zero

-N FILE

True if file exists and has been modified since it was last read

-o OPTNAME

True if the shell option optname is enabled [1]

-O FILE

True if file exists and is owned by the effective user id

-p FILE

True if file exists and is a named pipe (FIFO)

-r FILE

True if file exists and is readable

-R $VARNAME

True if the shell variable $VARNAME is set and is a name reference

-s FILE

True if file exists and has a size greater than zero

-S FILE

True if file exists and is a socket

-t FD

True if file descriptor fd is open and refers to a terminal

-u FILE

True if file exists and its set-user-id bit is set

-v $VARNAME

True if the shell variable $VARNAME is set (has been assigned a value) [2]

-w FILE

True if file exists and is writable

-x FILE

True if file exists and is executable

-z FILE or STRING

True if STRING or FILE is null

Test Expressions - File Comparison (1)

Compare Flags

Explainer

file1 -nt file2

True if file1 exists and is newer than file2

file1 -ot file2

True if file1 exists and is older than file2

file1 -ef file2

True if file1 and file2 exist and refer to the same file

Test Expressions - File Comparison (2) Detailed

Compare Strings

Explainer

s1 == s2

True if strings s1 and s2 are equal

s1 = s2

True if strings s1 and s2 are equal

s1 != s2

True if strings s1 and s2 are not equal

s1 < s2

True if string s1 comes before s2 based on the binary value of their characters

s1 > s2

True if string s1 comes after s2 based on the binary value of their characters

Note

Bash-based conditionals - #!/bin/bash - usually prefer you to use double-brackets, [[ ]]. When you use [[ ]], you have to use double-equals - ==. You can still use the single-brackets with single-equals =.

But when using sh - #!/bin/sh - it prefers single-brackets - [ ]. When you use the single-brackets, you use single-equals - =.

Test Expressions - File Comparison (3) MATH SPECIFIC

Compare Strings

Explainer

n1 -eq n2

True if the integers n1 and n2 are algebraically equal

n1 -ne n2

True if the integers n1 and n2 are not algebraically equal

n1 -gt n2

True if the integer n1 is algebraically greater than the integer

n1 -ge n2

True if the integer n1 is algebraically greater than or equal to the integer n2

n1 -lt n2

True if the integer n1 is algebraically less than the integer n2

n1 -le n2

True if the integer n1 is algebraically less than or equal to the integer n2

Note

See man test for more explanations.