bash: ifConditions: if, elif, else, test brackets and case
if runs a command and branches on its exit status: 0 means true. The command is usually a test: [[ ]] for files and strings, (( )) for numbers, or any real command like grep -q. case picks between many string patterns. Together they let a script check its environment before doing anything risky.
if CMD; then ...; elif CMD; then ...; else ...; fi case WORD in PATTERN) ...;; esacA monitoring check must print OK, WARNING or CRITICAL for a filesystem and exit 0, 1 or 2, like a Nagios plugin.
ifRuns the command list that follows and checks its exit status. 0 is true, anything else false.
if is not a comparison operator: it executes the command after it and looks only at the exit status. [ is a real command (also /usr/bin/[) that evaluates its arguments and exits 0 or 1, which is why it needs spaces around it and a closing ] argument. Because [ is an ordinary command, the shell has already expanded and word-split its arguments, so an empty or multi-word variable changes the number of arguments and produces errors like 'unary operator expected'. [[ ]] is a bash keyword parsed before expansion: no word splitting or globbing happens inside, && || and ( ) work, == does glob matching and =~ regex matching. (( )) evaluates C-style integer arithmetic and returns 0 when the result is non-zero, so (( usage >= 90 )) reads naturally. Inside [[ ]], > and < compare strings alphabetically, not numbers. case compares one word against glob patterns top to bottom and runs the first branch that matches.
[[ -f F ]] / -d / -eRegular file exists / directory exists / anything exists-r -w -x FReadable / writable / executable by the current user-s FExists and is not empty-z S / -n SString is empty / not emptyS1 == S2, !=String equal / not equal; right side may be a glob (prod*)S =~ REGEXRegex match; captures land in BASH_REMATCH(( a >= b ))Integer comparison: == != < <= > >=-eq -ne -lt -le -gt -geInteger comparison inside [ ] or [[ ]]F1 -nt F2F1 is newer than F2 (modification time)! CMDNegate the exit status of a command or testcase $x in a|b) ;; *) ;; esacMatch a value against several glob patternsif [ $status = "failed" ]If $status is empty or contains spaces, [ gets the wrong number of arguments: 'unary operator expected' or 'too many arguments'.
if [[ $status == failed ]] # or: [ "$status" = failed ]if [[ $count > 9 ]]> inside [[ ]] compares strings alphabetically, so 10 > 9 is false.
if (( count > 9 )) # or: [[ $count -gt 9 ]]if [$x -eq 1] or if [ $x -eq 1][ is a command and ] is its last argument; both need spaces around them.
if [ "$x" -eq 1 ]if [ grep -q ERROR app.log ]The brackets make it a test of the words 'grep', '-q'... instead of running grep.
if grep -q ERROR app.log; thencmd && echo ok || echo failed used as if/elseIf echo ok itself fails (e.g. stdout closed), the 'failed' branch also runs. It's not a true if/else.
if cmd; then echo ok; else echo failed; fiTry these on a Linux machine of your own. Each task has a hint and a solution.
Write a one-liner that prints 'exists' if /etc/hosts is a regular file and 'missing' otherwise.
Print 'big log' if ~/logs/app.log has more than 1000 lines.
Set env=prod and write a case statement that prints 'careful' for prod or production, 'fine' for anything else.
Print 'FATAL found' only if ~/logs/app.log contains FATAL, using grep's exit status (no brackets).
bash: ifConditions: if, elif, else, test brackets and case
if runs a command and branches on its exit status: 0 means true. The command is usually a test: [[ ]] for files and strings, (( )) for numbers, or any real command like grep -q. case picks between many string patterns. Together they let a script check its environment before doing anything risky.
if CMD; then ...; elif CMD; then ...; else ...; fi case WORD in PATTERN) ...;; esacA monitoring check must print OK, WARNING or CRITICAL for a filesystem and exit 0, 1 or 2, like a Nagios plugin.
ifRuns the command list that follows and checks its exit status. 0 is true, anything else false.
if is not a comparison operator: it executes the command after it and looks only at the exit status. [ is a real command (also /usr/bin/[) that evaluates its arguments and exits 0 or 1, which is why it needs spaces around it and a closing ] argument. Because [ is an ordinary command, the shell has already expanded and word-split its arguments, so an empty or multi-word variable changes the number of arguments and produces errors like 'unary operator expected'. [[ ]] is a bash keyword parsed before expansion: no word splitting or globbing happens inside, && || and ( ) work, == does glob matching and =~ regex matching. (( )) evaluates C-style integer arithmetic and returns 0 when the result is non-zero, so (( usage >= 90 )) reads naturally. Inside [[ ]], > and < compare strings alphabetically, not numbers. case compares one word against glob patterns top to bottom and runs the first branch that matches.
[[ -f F ]] / -d / -eRegular file exists / directory exists / anything exists-r -w -x FReadable / writable / executable by the current user-s FExists and is not empty-z S / -n SString is empty / not emptyS1 == S2, !=String equal / not equal; right side may be a glob (prod*)S =~ REGEXRegex match; captures land in BASH_REMATCH(( a >= b ))Integer comparison: == != < <= > >=-eq -ne -lt -le -gt -geInteger comparison inside [ ] or [[ ]]F1 -nt F2F1 is newer than F2 (modification time)! CMDNegate the exit status of a command or testcase $x in a|b) ;; *) ;; esacMatch a value against several glob patternsif [ $status = "failed" ]If $status is empty or contains spaces, [ gets the wrong number of arguments: 'unary operator expected' or 'too many arguments'.
if [[ $status == failed ]] # or: [ "$status" = failed ]if [[ $count > 9 ]]> inside [[ ]] compares strings alphabetically, so 10 > 9 is false.
if (( count > 9 )) # or: [[ $count -gt 9 ]]if [$x -eq 1] or if [ $x -eq 1][ is a command and ] is its last argument; both need spaces around them.
if [ "$x" -eq 1 ]if [ grep -q ERROR app.log ]The brackets make it a test of the words 'grep', '-q'... instead of running grep.
if grep -q ERROR app.log; thencmd && echo ok || echo failed used as if/elseIf echo ok itself fails (e.g. stdout closed), the 'failed' branch also runs. It's not a true if/else.
if cmd; then echo ok; else echo failed; fiTry these on a Linux machine of your own. Each task has a hint and a solution.
Write a one-liner that prints 'exists' if /etc/hosts is a regular file and 'missing' otherwise.
Print 'big log' if ~/logs/app.log has more than 1000 lines.
Set env=prod and write a case statement that prints 'careful' for prod or production, 'fine' for anything else.
Print 'FATAL found' only if ~/logs/app.log contains FATAL, using grep's exit status (no brackets).