Skip to content

Chapter 3 of 8

Conditionals and Tests

Conditional execution in Bash revolves around if, elif, else, and fi. The condition itself is a list of commands whose exit status determines the branch: zero is true and non-zero is false. The three most common test constructs are [ ], [[ ]], and (( )). The single-bracket [ ... ] is the POSIX test builtin: it is portable but performs word splitting on its operands, so variables inside it must be quoted. The double-bracket [[ ... ]] is a Bash keyword that does not word-split its operands and adds Bash-specific features, most notably == glob matching and =~ regular-expression matching. The arithmetic form (( ... )) evaluates an integer expression and returns 0 (true) when the result is non-zero.

File-test operators inside [[ ]] include -e (exists), -f (regular file), -d (directory), -L (symlink), -r, -w, -x (readable, writable, executable), and -s (size greater than zero); they are negated with !. String tests include -z (empty), -n (non-empty), == and != (with the right-hand side optionally a glob), and < and > for lexicographic comparison. For integer comparison, prefer (( a == b )) or the [[ ]] operators -eq, -ne, -lt, -le, -gt, and -ge; do not use the lexicographic < and > operators on integers. A classic pitfall illustrates why quoting matters: if [ \(foo = "bar" ] fails with a syntax error when foo is empty, because word splitting expands it to [ = "bar" ]. The fix is to quote the variable, as in if [ "\)foo" = "bar" ], or to use [[ "$foo" == "bar" ]], which avoids the issue altogether.

Pattern-based multi-way branching uses a case statement, whose right-hand side supports glob patterns and | alternations and which ends with esac. Regex matching lives in [[ ]] as well: [[ "\(s" =~ ^[0-9]+\) ]] tests for an all-digits string, and capture groups after a successful match are available through the \({BASH_REMATCH[1]}, \){BASH_REMATCH[2]}, ... array. To detect which operating system the script is running on, [[ "$(uname)" == "Linux" ]] (or a case over uname -s) gates platform-specific code, and [[ $EUID -eq 0 ]] checks whether the script is running as root.

All chapters
  1. 1Foundations of Bash Scripting
  2. 2Variables, Expansion, Quoting, and Strict Mode
  3. 3Conditionals and Tests
  4. 4Loops and Iteration
  5. 5Functions, Sourcing, and Command-Line Arguments
  6. 6Arrays, Strings, Substitutions, and Arithmetic
  7. 7Input/Output, Redirection, and File Handling
  8. 8Process Control, Scheduling, and Robust Practices

Drill it

Reading is not remembering. These come from the Bash Scripting For Automation deck:

Q

What is Bash?

Bash (Bourne Again SHell) is a Unix shell and command language written as a free software replacement for the Bourne shell (sh). It is the default login shell o...

Q

What file extension is conventionally used for Bash scripts?

.sh. While not strictly required for execution, .sh signals intent and lets tooling treat the file as a shell script.

Q

What must the first line of an executable Bash script be?

A shebang line, e.g. #!/usr/bin/env bash or #!/bin/bash, which tells the kernel which interpreter to invoke.

Q

What command makes a script file executable?

chmod +x script.sh (or chmod 755 script.sh).