This lesson sits in the Shell Scripting & Bash course hub if you want the full sequence.
Almost every script uses bash if else style branching: run a test or command, and
pick a block based on its exit status. You will see the same idea under names like
if else bash, bash if then else, or else if bash—in the shell the second
keyword is elif, not else if. This page covers the grammar (if / then /
else / fi), elif chains and why order matters, and how this ties to
string and
number comparisons, plus where [[
differs from [. Use it with for,
while, and functions
when if sits inside larger control flow. When one variable must match many fixed
strings (for example $1 is start or stop), Bash case statement is often clearer than a long elif chain.
Tested all the commands and code from this article on Ubuntu 25.04, kernel 6.14.0-37-generic, Bash 5.2.37.
Exit status: what if actually tests
if looks at the exit code of the list that follows it. 0 means success (true),
any non-zero value means failure (false). [[ … ]] and [ … ] are commands that
return 0 or 1; normal commands like grep or test -f work the same way.
if … then … fi (no else)
VAR1=10
VAR2=5
if [[ "$VAR1" -ge "$VAR2" ]]; then
echo "$VAR2 is less than or equal to $VAR1"
fiOutput:
5 is less than or equal to 10One-line form (use sparingly for readability):
VAR1=10 VAR2=5; if [[ "$VAR1" -ge "$VAR2" ]]; then echo "ok"; fiOutput:
okif … then … else … fi (classic bash if else)
VAR1=10
VAR2=50
if [[ "$VAR1" -ge "$VAR2" ]]; then
echo "first branch"
else
echo "else branch"
fiOutput:
else branchThe else branch runs when the test returns non-zero.
elif chains (else if bash → write elif)
x=2
if [[ "$x" -eq 1 ]]; then
echo "one"
elif [[ "$x" -eq 2 ]]; then
echo "two"
else
echo "other"
fiOutput:
twoOrder matters
Conditions are evaluated top to bottom; the first match wins. If the first test is
too broad, later elif lines never run:
a=10
b=10
if [[ "$a" -ge "$b" ]]; then
echo "first: greater-or-equal"
elif [[ "$a" -eq "$b" ]]; then
echo "second: equal"
fiOutput:
first: greater-or-equalFor equality-only logic, test -eq (or string ==) before broader -ge checks,
or split into clearer branches.
[[ … ]] vs [ … ]
[[is a Bash keyword with friendlier parsing (often fewer backslashes, safer default handling of empty variables).[is thetestbuiltin and is what you lean on for POSIX/bin/shportability.
When comparisons get subtle, read the dedicated comparison articles linked above instead of duplicating every operator here.
Combining conditions with && and ||
Inside [[ you can combine tests:
n=3
if [[ "$n" -ge 1 && "$n" -le 5 ]]; then
echo "in range"
fiOutput:
in rangeKeep tests short; for long predicates, assign sub-results to variables or use early
return/continue in functions and loops.
Nested if
Nothing special syntactically—just another if inside the then (or else) of an
outer if:
n=7
if [[ -n "$n" ]]; then
if [[ "$n" -gt 0 ]]; then
echo "positive"
else
echo "non-positive"
fi
else
echo "empty input"
fiOutput:
positiveSame structure with n=-1:
n=-1
if [[ -n "$n" ]]; then
if [[ "$n" -gt 0 ]]; then
echo "positive"
else
echo "non-positive"
fi
else
echo "empty input"
fiOutput:
non-positivePractical habits and pitfalls
- Quote variables in tests:
[[ "$var" = foo ]]avoids word-splitting surprises. - Do not trust
$?immediately afterechoinside the same branch if you meant the condition’s status—echooverwrites$?. - Prefer
[[for Bash-only scripts; use[whenshcompatibility matters. elifis notelse if—only oneif/fipair wraps the whole chain.
Summary
Bash if then else is just exit-code branching: if list; then … elif list; then … else … fi, where each list is usually [[ … ]], [ … ], or a command.
Else if bash is written elif. Put broader checks after stricter ones so the
right branch runs, quote expansions, and reach for [[ in Bash while remembering
[ for portable scripts. With that, if else in bash shell scripts stay readable
and predictable.
Further reading:

