← Back to Bash Course | Chapter 3: Control Flow | Lesson 10 of 14

Logical Operators

&&, ||, and ! let you combine or invert conditions so a command only runs when certain success/failure combinations happen.

&& for Sequential Success

&& runs the command on its right only if the command on its left exited with status 0. This is a compact way to chain steps that should only proceed if the previous one worked, without writing a full if block.

Example: && for Sequential Success

bash
#!/bin/bash
mkdir -p output_dir && echo "Directory ready, continuing"
cd output_dir && echo "Now inside output_dir: $(pwd)"

|| for Fallback on Failure

|| runs the command on its right only if the command on its left exited with a non-zero status. This is commonly used to provide a fallback action or error message when something fails.

Example: || for Fallback on Failure

bash
#!/bin/bash
grep -q "xyz" <<< "abc def" || echo "Pattern 'xyz' was not found, using fallback"

! to Negate a Condition

! inverts the exit status of the command or test immediately following it, turning success into failure and failure into success. Inside [ ] or [[ ]], it is placed directly before the condition being negated.

Example: ! to Negate a Condition

bash
#!/bin/bash
if [ ! -f nonexistent_file.txt ]; then
    echo "Confirmed: nonexistent_file.txt does not exist"
fi
if ! grep -q "zzz" <<< "hello world"; then
    echo "Confirmed: pattern not found"
fi

Combining && and || Together

&& and || can be chained on one line for a compact 'if success do X, else do Y' pattern, evaluated strictly left to right. Be careful with more complex combinations -- for anything beyond a simple two-way branch, a proper if/else is clearer and less error-prone.

Warning: If the middle command in an &&/|| chain can itself fail for reasons unrelated to the condition, the || fallback might run unexpectedly -- prefer if/else when the logic gets complex.

Example: Combining && and || Together

bash
#!/bin/bash
value=10
[ "$value" -gt 5 ] && echo "Value is greater than 5" || echo "Value is 5 or less"
Common Mistakes
  1. Thinking &&/|| operate on true/false booleans; they actually chain based on a command's exit status (0 = success), so command1 && command2 really means 'run command2 only if command1 exited 0'.
  2. Misplacing ! when negating inside [ ] vs [[ ]]; ! needs to go right before the expression ([ ! -f file ]), not before the whole if.
  3. Chaining many &&/|| together without parentheses/grouping and being surprised by the result, since && and || are evaluated left to right with equal precedence, unlike in some other languages.
Chapter Summary
  • cmd1 && cmd2 runs cmd2 only if cmd1 exited with status 0 (succeeded).
  • cmd1 || cmd2 runs cmd2 only if cmd1 exited with a non-zero status (failed).
  • ! negates the exit status of the command or test that follows it -- success becomes failure and vice versa.
  • Inside [[ ]], && and || combine sub-conditions directly; outside of [[ ]]/(( )), they combine whole commands.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.