Topic 6.2
Variables, Conditionals & Loops
In one line
Variables store values, conditionals make decisions, and loops repeat work — the same three building blocks every programming language has, expressed in bash's own (occasionally quirky) syntax.
Key ideas
- 01
Bash variables are assigned with NO spaces around the
=sign (NAME=value, neverNAME = value— the latter is interpreted as running a command called NAME with arguments, a genuinely common beginner error) and read back with a$prefix (echo $NAME, or${NAME}when you need to disambiguate it from surrounding text). - 02
$(command)(command substitution) captures a command's OUTPUT into a variable —TODAY=$(date +%Y-%m-%d)runsdate, captures what it printed, and stores that text inTODAYfor later use in the script, a genuinely essential building block for any script that needs to act on a command's result. - 03
An
ifstatement in bash:if [ condition ]; then ... elif [ other ]; then ... else ... fi— note the spaces INSIDE the brackets are mandatory ([condition]without spaces is a syntax error), and the block must end with the literal wordfi('if' spelled backward, bash's consistent closing-keyword convention). - 04
Common test conditions:
[ -f file ](file exists and is a regular file),[ -d dir ](directory exists),[ "$a" = "$b" ](string equality — note=not==for portability, and always quote variables here to avoid errors when a variable is empty or contains spaces),[ $a -eq $b ](numeric equality —-eq,-lt,-gtetc. for numbers specifically, a genuinely easy detail to mix up with string comparison). - 05
A
forloop:for i in 1 2 3; do echo $i; doneiterates over a list of values;for file in *.log; do echo $file; doneiterates over every file matching a wildcard (Phase 0's globbing, reused directly) — genuinely one of the most common loop shapes in real scripts, processing every file matching a pattern one at a time. - 06
A
whileloop:while [ condition ]; do ... donerepeats as long as the condition stays true — commonly used withwhile read line; do ... done < file.txtto process a file LINE BY LINE, a pattern that shows up constantly when a script needs to act on each line of some input individually.
In your stack
- →
A real deployment script might use
if [ -f target/app.jar ]; then java -jar target/app.jar; else echo "Build first!"; exit 1; fi— checking a precondition before attempting the actual action, exactly the kind of defensive check that separates a script you can trust from one that fails confusingly when run out of order.
Code & diagrams
Every quirk called out above, demonstrated directly.
#!/usr/bin/env bash
# Variable assignment — NO spaces around =
NAME="production-server"
COUNT=3
# Command substitution
TODAY=$(date +%Y-%m-%d)
echo "Today is $TODAY"
# Conditional: does a file exist?
if [ -f "/etc/hosts" ]; then
echo "hosts file exists"
else
echo "hosts file missing"
fi
# String vs numeric comparison
STATUS="active"
if [ "$STATUS" = "active" ]; then
echo "Service is active"
fi
if [ $COUNT -gt 2 ]; then
echo "Count is greater than 2"
fiThe two most common loop shapes in real scripts.
#!/usr/bin/env bash
# for loop over a list
for i in 1 2 3; do
echo "Iteration: $i"
done
# for loop over files matching a wildcard
for file in *.sh; do
echo "Found script: $file"
done
# while loop reading a file line by line
while read -r line; do
echo "Line: $line"
done < /etc/hostsExplain it without notes
Why does NAME = value (with spaces) fail in bash, while NAME=value works?
What's the practical difference between [ "$a" = "$b" ] and [ $a -eq $b ], and why does using the wrong one matter?
Practice
Write a script that loops through every .txt file in a directory and prints its name along with its line count (using wc -l from Phase 2).
Write a script using an if/elif/else chain that checks a variable representing a status ("running", "stopped", "unknown") and prints a different message for each case.
Trade-offs
- ↔
Bash's conditional and comparison syntax is genuinely quirky and error-prone compared to most general-purpose languages (missing a space, or quoting a variable incorrectly, can silently produce a wrong result rather than a clear error) — for anything beyond a moderate amount of logic, many teams switch to Python for the actual logic while keeping bash for the thin orchestration layer around it, a trade-off worth recognizing rather than forcing everything into bash out of habit.
Done when you can
I can declare and read a bash variable, and use command substitution to capture a command's output.
I can write an if/elif/else conditional with correct bracket spacing and quoting.
I can write both a for loop (over a list or wildcard) and a while loop (reading a file line by line).