Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Shell Script Dictionary
  3. if / elif / else

if / elif / else

Since: POSIX(sh互換)

The if statement in Shell Script branches execution based on whether a condition is true (exit status 0) or false (non-zero). Conditions are evaluated using the test command (equivalent to [) or the bash-extended [[ compound command. It handles string comparison, numeric comparison, and file existence checks, and forms the core of script control flow.

Basic Syntax

An if statement is closed with fi. Use elif to chain additional conditions, and else to run a block when none of the conditions match.

KeywordMeaningDescription
ifStart of conditional branchRuns the then block when the following command exits with status 0.
thenStart of the true branchBegins the block to execute when the if or elif condition is true.
elifAdditional condition (else if)Specifies an additional condition to evaluate when the previous condition was false. Multiple elif clauses can be chained.
elseFallback branchBegins the block to execute when all conditions are false.
fiEnd of conditional branchCloses the if block (the word "if" spelled backwards).
# Basic structure of an if statement
if command; then
    # Runs when the command exits with status 0 (true)
    action_a
elif another_command; then
    # Runs when the first condition is false and this one exits with 0 (true)
    action_b
else
    # Runs when all conditions are false
    action_c
fi

The test Command and [ ]

[ is an alias for the test command. When you write [ condition ], it returns exit status 0 (true) if the condition holds, or 1 (false) if it does not. Because ] marks the end of the arguments, a space before the closing bracket is required.

SyntaxDescription
test conditionEvaluates the condition. POSIX-compliant and works in sh.
[ condition ]Exactly equivalent to test. Spaces inside the brackets are required.
[[ condition ]]A compound command that extends bash/zsh. Supports && / ||, glob pattern matching, and regular expressions (=~). Not available in sh.

String Comparison

Use = (or ==) and != for string comparisons. Always wrap variables in double quotes — without them, an empty variable causes an error.

OperatorTrue whenDescription
[ "$a" = "$b" ]Exact matchTrue when strings a and b are equal. POSIX-compliant, works in sh.
[ "$a" == "$b" ]Exact match (bash)Equivalent to =. Inside [[ ]], treated as a glob pattern match.
[ "$a" != "$b" ]Not equalTrue when strings a and b differ.
[ -z "$a" ]Empty stringTrue when string a has a length of 0 (is empty).
[ -n "$a" ]Non-empty stringTrue when string a has a length of 1 or more.
[[ "$a" =~ regex ]]Regex matchAvailable only in bash [[. The match result is stored in BASH_REMATCH.

Numeric Comparison

Use dedicated flags for numeric comparisons. Note that < and > perform lexicographic (string) comparison, so do not use them for numbers.

OperatorMeaningDescription
[ "$a" -eq "$b" ]EqualTrue when numbers a and b are equal.
[ "$a" -ne "$b" ]Not equalTrue when numbers a and b differ.
[ "$a" -lt "$b" ]Less thanTrue when number a is less than b.
[ "$a" -le "$b" ]Less than or equalTrue when number a is less than or equal to b.
[ "$a" -gt "$b" ]Greater thanTrue when number a is greater than b.
[ "$a" -ge "$b" ]Greater than or equalTrue when number a is greater than or equal to b.

File Tests

Use flags such as -f, -d, and -e to check the state of files and directories. These are commonly used to verify file existence or check permissions before running a script.

OperatorTrue whenDescription
[ -e "$path" ]ExistsTrue when the path exists — whether it is a file, directory, symbolic link, etc.
[ -f "$path" ]Regular fileTrue when the path is a regular file (not a directory or device file).
[ -d "$path" ]DirectoryTrue when the path is a directory.
[ -r "$path" ]ReadableTrue when you have read permission on the path.
[ -w "$path" ]WritableTrue when you have write permission on the path.
[ -x "$path" ]ExecutableTrue when you have execute permission on the path.
[ -s "$path" ]Size greater than 0True when the file exists and is not empty.
[ -L "$path" ]Symbolic linkTrue when the path is a symbolic link.

Logical Operators

To combine multiple conditions, use && / || inside [[ ]], or -a / -o inside [ ]. Using && / || within [[ ]] is more readable and generally preferred.

SyntaxMeaningDescription
[[ condA && condB ]]ANDTrue when both A and B are true. Requires [[ ]].
[[ condA || condB ]]ORTrue when either A or B is true. Requires [[ ]].
[ condA ] && [ condB ]AND (POSIX-compliant)Connects two [ ] tests with &&. Works in sh.
[ condA -a condB ]AND (older syntax)Works inside [ ], but prone to problems when variables are empty. Not recommended.
! conditionNOT (negation)Negates the condition. Used as [ ! -f "$path" ] inside [ ].

Sample Code

kof_string_compare.sh
#!/bin/bash
# -----------------------------------------------
#  Demonstrates string comparison with if
#  using KOF (The King of Fighters) characters
# -----------------------------------------------

# -----------------------------------------------
#  Set team members into variables
# -----------------------------------------------

# Members of the Kusanagi team in KOF
team_kusanagi=("Kusanagi Kyo" "Nikaido Benimaru" "Daimon Goro")

# Character name to check (set directly into a variable here)
input_name="Kusanagi Kyo"

echo "=== Exact string match ==="

# Use = to check for an exact string match (always quote variables with double quotes)
if [ "$input_name" = "Kusanagi Kyo" ]; then
    echo "${input_name} is the leader of the Kusanagi team."
elif [ "$input_name" = "Nikaido Benimaru" ]; then
    echo "${input_name} is a fighter who wields flames."
elif [ "$input_name" = "Daimon Goro" ]; then
    echo "${input_name} is the strongest judoka."
else
    echo "${input_name} is not a member of the Kusanagi team."
fi

echo ""
echo "=== Empty string check ==="

# Use -z to check whether a string is empty
fighter=""
if [ -z "$fighter" ]; then
    echo "No fighter name was entered."
else
    echo "Fighter name: ${fighter}"
fi

echo ""
echo "=== String inequality ==="

rival="Yagami Iori"

# Use != to check whether strings differ
if [ "$rival" != "Kusanagi Kyo" ]; then
    echo "${rival} is the rival of Kusanagi Kyo."
fi
$ chmod +x kof_string_compare.sh
$ ./kof_string_compare.sh
=== Exact string match ===
Kusanagi Kyo is the leader of the Kusanagi team.

=== Empty string check ===
No fighter name was entered.

=== String inequality ===
Yagami Iori is the rival of Kusanagi Kyo.
kof_numeric_compare.sh
#!/bin/bash
# -----------------------------------------------
#  Demonstrates numeric comparison with if
#  using KOF characters
# -----------------------------------------------

# -----------------------------------------------
#  Set each character's power level into variables
# -----------------------------------------------

declare -A power
power["Kusanagi Kyo"]=9500
power["Yagami Iori"]=9200
power["Leona"]=8800
power["Terry Bogard"]=9000
power["Mai Shiranui"]=7500

target="Kusanagi Kyo"
score=${power[$target]}

echo "=== Numeric comparison ==="
echo "${target} power level: ${score}"
echo ""

# Use -ge (greater than or equal) to determine rank by power level
if [ "$score" -ge 9500 ]; then
    echo "Rank: S class (Overlord)"
elif [ "$score" -ge 9000 ]; then
    echo "Rank: A class (Legendary Fighter)"
elif [ "$score" -ge 7000 ]; then
    echo "Rank: B class (Advanced)"
else
    echo "Rank: C class (Intermediate)"
fi

echo ""
echo "=== Rank for all characters ==="

# Determine rank for all characters using a for loop
for chara in "${!power[@]}"; do
    val=${power[$chara]}
    if [ "$val" -ge 9500 ]; then
        rank="S"
    elif [ "$val" -ge 9000 ]; then
        rank="A"
    elif [ "$val" -ge 7000 ]; then
        rank="B"
    else
        rank="C"
    fi
    echo "  ${chara}: ${val} (Rank ${rank})"
done
$ chmod +x kof_numeric_compare.sh
$ ./kof_numeric_compare.sh
=== Numeric comparison ===
Kusanagi Kyo power level: 9500

Rank: S class (Overlord)

=== Rank for all characters ===
  Kusanagi Kyo: 9500 (Rank S)
  Yagami Iori: 9200 (Rank A)
  Leona: 8800 (Rank B)
  Terry Bogard: 9000 (Rank A)
  Mai Shiranui: 7500 (Rank B)
kof_file_test.sh
#!/bin/bash
# -----------------------------------------------
#  Demonstrates file test operators using
#  KOF character data files
# -----------------------------------------------

# -----------------------------------------------
#  Create test files and directories
# -----------------------------------------------

# Create a working directory
work_dir="./kof_data"
mkdir -p "$work_dir"

# Create character data files
echo "Name: Kusanagi Kyo, Team: Kusanagi, Move: Yami Barai" > "${work_dir}/kusanagi_kyo.txt"
echo "Name: Yagami Iori, Team: Yagami, Move: Yasakani no Magatama" > "${work_dir}/yagami_iori.txt"
touch "${work_dir}/empty_fighter.txt"    # Create an empty file (size 0)

echo "=== File tests ==="
echo ""

# Use -f to check whether a file exists
target_file="${work_dir}/kusanagi_kyo.txt"
if [ -f "$target_file" ]; then
    echo "[OK] ${target_file} is a regular file."
else
    echo "[NG] ${target_file} was not found."
fi

echo ""

# Use -d to check whether a path is a directory
if [ -d "$work_dir" ]; then
    echo "[OK] ${work_dir} is a directory."
fi

echo ""

# Use -s to check whether a file is non-empty
echo "=== File content check ==="
for f in "${work_dir}"/*.txt; do
    if [ -s "$f" ]; then
        echo "  [data] $(basename $f): has content"
    else
        echo "  [empty] $(basename $f): no content"
    fi
done

echo ""

# Use -r and -w to check read/write permissions
echo "=== Permission check ==="
check_file="${work_dir}/kusanagi_kyo.txt"
if [ -r "$check_file" ] && [ -w "$check_file" ]; then
    echo "${check_file} is readable and writable."
fi

# Remove the working directory and clean up
rm -rf "$work_dir"
echo ""
echo "Cleanup complete."
$ chmod +x kof_file_test.sh
$ ./kof_file_test.sh
=== File tests ===

[OK] ./kof_data/kusanagi_kyo.txt is a regular file.

[OK] ./kof_data is a directory.

=== File content check ===
  [empty] empty_fighter.txt: no content
  [data] kusanagi_kyo.txt: has content
  [data] yagami_iori.txt: has content

=== Permission check ===
./kof_data/kusanagi_kyo.txt is readable and writable.

Cleanup complete.

Comparing [ ] and [[ ]]

Feature[ ] (test)[[ ]] (bash extension)
POSIX complianceCompliant (works in sh).bash / zsh only. Not available in sh.
AND / ORUse -a / -o (not recommended), or write separate [ ] && [ ] tests.&& / || can be used directly.
Pattern matchingNot supported.== supports glob patterns (e.g., *).
Regular expressionsNot supported.=~ supports POSIX extended regular expressions.
Word splittingWord splitting occurs if variables are not quoted.Word splitting does not occur even without quoting (safer).
< / >Interpreted as redirection; must be escaped as \< / \>.Used directly as lexicographic string comparison operators.

Summary

The if statement in Shell Script branches based on a command's exit status (0 is true), chains additional conditions with elif, and closes with fi. Conditions are evaluated using the POSIX-compliant [ ] (equivalent to test) or the bash-extended [[ ]]. For string comparison, use =, !=, -z, and -n. For numeric comparison, use -eq, -ne, -lt, -le, -gt, and -ge. For file tests, use -f, -d, -e, -s, and others. Choose [ ] when portability matters, or [[ ]] when writing bash-specific scripts where readability and safety are priorities. For combining multiple conditions, [[ condA && condB ]] is recommended. See also for loop for combining if with loops.

If you find any errors or copyright issues, please .