Kahibaro
Discord Login Register

2.7.3 Conditionals

Understanding Conditionals in Shell Scripts

Conditionals let your script make decisions: “if this is true, do that; otherwise, do something else.” In shell scripting, this is mainly done with the if statement and test expressions.

This chapter assumes you already know how to write and run basic scripts and use variables.


Basic `if` Syntax

The basic form:

if COMMANDS_OR_TEST; then
    # commands if condition is true
fi

Example:

#!/bin/bash
if [ -f "/etc/passwd" ]; then
    echo "/etc/passwd exists"
fi

Key points:

Using `then` on Same or Next Line

Two equivalent styles:

if [ "$USER" = "root" ]; then
    echo "You are root"
fi
if [ "$USER" = "root" ]
then
    echo "You are root"
fi

Both are valid; choose one style and be consistent.


Exit Status and Truth in Shell

In shell conditionals:

This is backwards from many other languages.

You can use any command as a condition:

if ping -c 1 example.com >/dev/null 2>&1; then
    echo "Network looks OK"
else
    echo "Cannot reach example.com"
fi

Here ping itself is the test; no [ ] involved.


`if … else` and `if … elif … else`

`if … else`

if [ "$USER" = "root" ]; then
    echo "You are root"
else
    echo "You are not root"
fi

`if … elif … else`

Use elif (else-if) for multiple branches:

if [ "$HOUR" -lt 12 ]; then
    echo "Good morning"
elif [ "$HOUR" -lt 18 ]; then
    echo "Good afternoon"
else
    echo "Good evening"
fi

Evaluation order:

  1. First condition that is true runs its block.
  2. Remaining elif/else parts are skipped.

Testing Conditions with `[` and `test`

Most shell scripts use the [ (also called test) command in if:

if [ condition ]; then
    ...
fi

Important:

Example:

if [ "$ANSWER" = "yes" ]; then
    echo "You answered yes"
fi

Wrong (no spaces): if ["$ANSWER"="yes"]; then → will fail.

test is equivalent:

if test "$ANSWER" = "yes"; then
    echo "You answered yes"
fi

String Comparisons

Common string tests with [ … ]:

Examples:

if [ "$USER" = "root" ]; then
    echo "Running as root"
fi
if [ -z "$NAME" ]; then
    echo "NAME is empty"
else
    echo "Hello, $NAME"
fi

Always quote string variables ("$VAR") to avoid errors when they are empty or contain spaces.


Numeric Comparisons

For integers, use these operators with [ … ]:

Example:

if [ "$AGE" -lt 18 ]; then
    echo "You are under 18"
elif [ "$AGE" -ge 65 ]; then
    echo "You are 65 or older"
else
    echo "You are between 18 and 64"
fi

Do not use < or > inside [ … ] for numbers; those are for string ordering and will be treated specially by the shell (like redirection).


File Tests

The [ … ] command has many tests for files:

Common ones:

Examples:

FILE="/etc/passwd"
if [ -e "$FILE" ]; then
    echo "$FILE exists"
fi
if [ -f "$FILE" ]; then
    echo "$FILE is a regular file"
fi
if [ -r "$FILE" ]; then
    echo "$FILE is readable"
fi

Directory example:

DIR="/var/log"
if [ -d "$DIR" ]; then
    echo "$DIR is a directory"
fi

Combining Conditions: `!`, `-a`, `-o`, and `&&`/`||`

Negation with `!`

! in front of a test inverts its result:

if [ ! -f "/tmp/test.txt" ]; then
    echo "File does not exist"
fi

Logical AND / OR inside `[ … ]`

Some shells support:

Example (not recommended for new scripts):

if [ -f "$FILE" -a -r "$FILE" ]; then
    echo "File exists and is readable"
fi

These can behave differently across shells and can be confusing. Prefer using && and || with separate tests.

Using `&&` (AND) and `||` (OR)

You can chain full commands:

In an if:

if [ -f "$FILE" ] && [ -r "$FILE" ]; then
    echo "File exists and is readable"
fi
if [ "$ANSWER" = "yes" ] || [ "$ANSWER" = "y" ]; then
    echo "You agreed"
fi

This style is clearer and more portable than -a and -o.


`[` vs `[[` (Extended Test)

Many modern shells (including bash) support [[ … ]], which is more powerful and safer than [ … ]. It is not POSIX-standard, but is common in bash scripts.

Key differences:

Examples (bash-only):

#!/bin/bash
if [[ "$ANSWER" == y* ]]; then
    echo "You answered with something starting with 'y'"
fi
if [[ "$USER" == "root" || "$USER" == "admin" ]]; then
    echo "Privileged user"
fi

Inside [[ … ]], you usually don’t need to quote variables for simple string comparisons, but quoting is still good practice for consistency.


Using Command Results in Conditions

Instead of testing only variables or files, you can test whether commands succeed.

Example: check if a directory can be created:

if mkdir /tmp/testdir 2>/dev/null; then
    echo "Created directory"
else
    echo "Failed to create directory"
fi

mkdir is the condition. If it returns exit code 0 (success), the then block runs.

Example: checking if a user exists (using id):

if id "alice" >/dev/null 2>&1; then
    echo "User alice exists"
else
    echo "User alice does not exist"
fi

Redirecting output to /dev/null keeps the terminal clean while still using the command’s exit status.


`case` as an Alternative to Multiple `if`s (Briefly)

For multiple specific values of one variable, case is often cleaner than many elif branches:

#!/bin/bash
echo -n "Choose an option (start/stop/restart): "
read ACTION
case "$ACTION" in
    start)
        echo "Starting service..."
        ;;
    stop)
        echo "Stopping service..."
        ;;
    restart)
        echo "Restarting service..."
        ;;
    *)
        echo "Unknown option: $ACTION"
        ;;
esac

The case statement is another form of conditional, especially useful for menus. Its detailed use is typically covered in a more advanced scripting chapter.


Common Pitfalls with Conditionals

Some frequent problems and how to avoid them:

  1. Forgetting spaces with [ and ]:
    • Wrong: if ["$X"="5"]; then
    • Right: if [ "$X" = "5" ]; then
  2. Using = for numbers instead of -eq:
   # Numeric comparison: use -eq, -lt, -gt, etc.
   if [ "$N" -eq 10 ]; then
       echo "N is ten"
   fi
  1. Not quoting variables:
   # Wrong: unquoted, can break if NAME is empty or has spaces
   if [ $NAME = "Bob" ]; then
   # Right:
   if [ "$NAME" = "Bob" ]; then
  1. Using single = instead of == in [[ … ]]?

In [[ … ]], both = and == work for string comparison, so this is usually fine. In [ … ], stick with = (POSIX).

  1. Confusing [ and [[ syntax:

Don’t mix them on the same line:

   # Use one style:
   if [ "$X" = "1" ] && [ "$Y" = "2" ]; then
       ...
   fi
   # Or:
   if [[ "$X" = "1" && "$Y" = "2" ]]; then
       ...
   fi

Small Practical Examples

Check if a directory is writable before writing

#!/bin/bash
TARGET_DIR="/tmp"
if [ -d "$TARGET_DIR" ] && [ -w "$TARGET_DIR" ]; then
    echo "Writing file..."
    echo "Hello" > "$TARGET_DIR/hello.txt"
else
    echo "Cannot write to $TARGET_DIR"
fi

Simple yes/no prompt

#!/bin/bash
read -p "Do you want to continue? [y/N] " ANSWER
if [[ "$ANSWER" == "y" || "$ANSWER" == "Y" ]]; then
    echo "Continuing..."
else
    echo "Aborting."
fi

Conditionals are central to making your scripts react to different situations. Practice by:

In later scripting chapters, you’ll combine conditionals with loops and functions to build more powerful scripts.

Views: 71

Comments

Please login to add a comment.

Don't have an account? Register now!