Q1What does [ -f config.txt ] test?
Shell Script - Conditionals
Test files, strings and numbers with [ -f config.txt ], [ -z "$name" ] and [ "$count" -lt 5 ], branch with if / elif / else, and route multiple patterns with case — write and run each script, illustrated in a browser terminal.
Branch by comparing values — string and number comparisons
In a shell script you change what runs by checking whether strings match or numbers are larger.
For the check you use the test command, or [ ... ], which does the same thing.
The [ and ] need spaces just inside them, so you write [ "$count" -lt 5 ].
A true check returns exit code 0, and a false one returns 1.
Compare strings with = (equal) and != (not equal), and check for empty with -z (empty) or -n (non-empty).
Compare numbers with -eq (equal), -ne (not equal), -lt (less than) and -gt (greater than), and note that strings and numbers use different operators.
Wrap variables in double quotes like [ -z "$name" ] — that way the syntax stays valid even when the value is empty.
count=3
mode="dev"
[ "$count" -lt 5 ] && echo small # 3 is less than 5, so small
[ "$count" -gt 0 ] && echo positive # greater than 0, so positive
[ "$mode" = "prod" ] || echo other # not prod, so other
[ -z "$mode" ] || echo has-mode # not empty, so has-mode
[ ... ] returns exit code 0 when true and 1 when false; if runs then on true and else on false.| Syntax | Meaning | Example |
|---|---|---|
[ "$a" = "$b" ] | true if strings a and b are equal | [ "$mode" = "prod" ] |
[ "$a" != "$b" ] | true if strings a and b differ | [ "$mode" != "dev" ] |
[ -z "$v" ] | true if variable v is empty | [ -z "$name" ] && echo empty |
[ -n "$v" ] | true if variable v is not empty | [ -n "$name" ] && echo set |
[ "$a" -eq N ] | true if number a equals N | [ "$count" -eq 0 ] |
[ "$a" -ne N ] | true if number a is not N | [ "$count" -ne 0 ] |
[ "$a" -lt N ] | true if number a is less than N | [ "$count" -lt 10 ] |
[ "$a" -gt N ] | true if number a is greater than N | [ "$count" -gt 0 ] |
Check files and folders — -f / -d
In a script you often check whether a config file exists or an output folder is ready before going further.
Test for a file with -f (a regular file exists) and for a folder with -d (a directory exists).
When you only care that something exists regardless of its kind, use -e, and to check that it is not empty, use -s.
You write these checks with the same [ ... ] as for strings and numbers, passing a path like [ -f config.txt ].
They return exit code 0 when true and 1 when false, so combined with if or && / || you can write use it if it exists, create it if it does not initialization.
touch report.txt # create the material
[ -f report.txt ] && echo exists # the file exists, so exists
[ -d report.txt ] || echo notdir # not a directory, so notdir
mkdir logs # create the folder
[ -d logs ] && echo hasdir # the directory exists, so hasdir
-f tests for a regular file, -d for a directory, and -e for existence of any kind. The same path can give different results depending on what you ask.| Syntax | Meaning | Example |
|---|---|---|
[ -f f ] | true if f exists as a regular file | [ -f config.txt ] && echo found |
[ -d d ] | true if d exists as a directory | [ -d logs ] && echo dir |
[ -e p ] | true if p exists, any kind | [ -e data ] && echo there |
[ -s f ] | true if f exists and is not empty | [ -s log.txt ] && echo nonempty |
Split the flow — if / elif / else
if runs the then block only when the condition is true.
To try several conditions in turn use elif, for the case where none match add else, and close with fi.
Separate the parts with semicolons as in if condition; then action; fi, or split them across lines.
count=3
if [ "$count" -eq 0 ]; then
echo "none"
elif [ "$count" -lt 5 ]; then
echo "few ($count)"
else
echo "many ($count)"
fi # prints few (3)
if, it tries each condition and runs only the first branch that becomes true. If none are true, it goes to else.| Syntax | Meaning | Example |
|---|---|---|
if cond; then … fi | run when the condition is true | if [ -f f ]; then echo ok; fi |
then | start the body when true | if [ -f f ]; then echo ok; fi |
elif cond; then … | try the next when the previous is false | elif [ "$n" -lt 5 ]; then … |
else … | run when none are true | else echo other; fi |
fi | close the if | if …; then …; fi |
Route multiple patterns — case
When you match one value against many candidates, case reads more clearly.
It has the form case value in pattern) action ;; esac, where you end each pattern with ;; and catch the no-match case with *).
It makes the intent of the branching clearer than stacking many if levels.
action="start"
case "$action" in
start) echo "starting service" ;;
stop) echo "stopping service" ;;
*) echo "unknown action: $action" ;;
esac # prints starting service
case matches the value against patterns from the top, runs only the first matching branch, and closes with esac. *) is the no-match case.| Syntax | Meaning | Example |
|---|---|---|
case x in pat) … ;; esac | route a value to several patterns | case "$1" in start) … ;; esac |
pat) | a pattern matched against the value | start) echo go ;; |
;; | end of each case action | start) echo go ;; |
*) | the no-match case | *) echo other ;; |
esac | close the case | case x in …; esac |
Knowledge Check
Answer each question one by one.
Q2Which keyword tries another condition when the previous one was false?
Q3Which symbol marks the end of each pattern's action in case?