&&(AND) / ||(OR) / !(NOT) / ;(Sequential) / &(Background)
| Since: | All Linux | |
|---|---|---|
| macOS(2001 Cheetah) | ||
| Bash 1.0(1989) |
The operators ; (semicolon), && (AND), || (OR), and ! (NOT) are used to chain commands together. They let you express execution order and conditional branching as a one-liner. Behavior is determined by the exit status of each command (0 = success, non-zero = failure).
Syntax
A semicolon (;) runs the next command regardless of whether the previous one succeeded or failed.
command1 ; command2
&& runs command2 only if command1 succeeds (exit status 0).
command1 && command2
|| runs command2 only if command1 fails (non-zero exit status).
command1 || command2
! inverts the exit status of a command (0 becomes 1, non-zero becomes 0).
! command
& (single ampersand) runs a command in the background. It is completely different from &&.
command &
Operator List
| Operator | Name | Description |
|---|---|---|
| cmd1 ; cmd2 | Semicolon (sequential) | Runs cmd2 regardless of whether cmd1 succeeded or failed. |
| cmd1 && cmd2 | AND | Runs cmd2 only if cmd1 succeeds (exit status 0). |
| cmd1 || cmd2 | OR | Runs cmd2 only if cmd1 fails (non-zero exit status). |
| ! cmd | NOT | Inverts the exit status of cmd (0 becomes 1, non-zero becomes 0). |
| cmd & | Background execution | Starts cmd as a background process. Not the same as &&. |
Sample Code
A semicolon (;) runs the next command regardless of the previous result. Here, a backup of an investigation report and a log entry are run in sequence.
cp kogami_report.txt kogami_report.bak ; echo "Backup complete" Backup complete
&& runs the next command only when the previous one succeeds. The following example moves into a directory only after successfully creating it.
mkdir /tmp/case_files && cd /tmp/case_files mkdir /tmp/case_files && cd /tmp/case_files mkdir: /tmp/case_files: File exists
Chain directory creation, navigation, and file creation in one line. The sequence stops at the first failure.
mkdir /tmp/investigation && cd /tmp/investigation && touch crime_coefficient.sh
|| runs a fallback command when the previous one fails. If the log file does not exist, create it.
cat case_report.log || echo "Log file not found. Creating a new one." > case_report.log
A common pattern: display an error message and exit the script if a command fails.
cp analysis.csv /backup/ || { echo "Backup failed: $?" >&2; exit 1; }
! (NOT) inverts the exit status. The following example creates a directory if it does not already exist.
! [ -d /tmp/reports ] && mkdir /tmp/reports && echo "Directory created" Directory created
Combining && and || lets you handle both the success and failure paths in one line.
grep "Kogami Shinya" /etc/allowed_users && echo "Access granted" || echo "Access denied" Kogami Shinya Access granted
crime_coefficient.sh
#!/bin/bash # Crime coefficient check script LOG_FILE="/var/log/psycho_pass/case_report.log" BACKUP_DIR="/backup/investigation" # Create the log directory if it does not exist [ -d "$(dirname $LOG_FILE)" ] || mkdir -p "$(dirname $LOG_FILE)" # Create backup dir -> copy log -> record result mkdir -p "$BACKUP_DIR" \ && cp "$LOG_FILE" "$BACKUP_DIR/case_report_$(date +%Y%m%d).log" \ && echo "$(date): Backup succeeded" >> "$LOG_FILE" \ || echo "$(date): Backup failed" >> "$LOG_FILE"
Overview
&& and || work based on the exit status ($?) of each command. An exit status of 0 means success; anything else (1–255) means failure. Most commands return 0 on success and 1 or 2 on error.
When set -e is enabled, the script exits immediately if any command fails. However, if a failing command appears on the left side of ||, the shell treats it as part of a conditional expression and does not trigger set -e. This can cause errors to be silently swallowed, so care is needed.
& (single ampersand) starts a command as a background process. && (double ampersand) is the AND operator. They look similar but behave completely differently — typos between the two are a common source of bugs.
Common Mistakes
Common Mistake 1: Confusing && with &
&& (AND) and & (background execution) differ by just one character but have completely different meanings.
cp analysis.csv /backup/ & echo "Done" Done [1] 1234
The above uses &, so cp runs in the background while echo runs immediately — "Done" is printed before the copy finishes. To print "Done" only after a successful copy, use &&.
cp analysis.csv /backup/ && echo "Done" Done
A particularly tricky case is appending & at the end of an && chain.
cmd1 && cmd2 &
This is interpreted as "run (cmd1 && cmd2) in the background". The entire AND chain — run cmd2 if cmd1 succeeds — is backgrounded as a single unit.
Common Mistake 2: set -e does not fire when || is present
In a script with set -e, a failing command on the left side of || does not abort the script (which is the intended behavior). However, when a function call is on the left side of ||, errors inside the function are also not caught by set -e.
check.sh
#!/bin/bash
set -e
check_file() {
cat /nonexistent/kogami_report.txt
echo "Does this line execute?"
}
check_file || echo "File not found"
echo "Script continues"
The following example demonstrates this:
bash check.sh cat: /nonexistent/kogami_report.txt: No such file or directory Does this line execute? Script continues
Even though cat fails inside the function, set -e does not trigger because || is present. The echo after cat runs, and since it succeeds, the function's overall exit status becomes 0. As a result, the right side of || ("File not found") is not executed either. Combining set -e with || can produce counter-intuitive behavior, so thorough testing is important.
If you find any errors or copyright issues, please contact us.