Skip to content

Shell Operators

OperatorNameBehavior
A ; BSemicolonRun B after A regardless of A’s exit status
A && BANDRun B only if A succeeds (exit code 0)
A || BORRun B only if A fails (non-zero exit code)
A | BPipeSend A’s stdout as B’s stdin
Terminal window
# Always run both
mkdir /tmp/work ; cd /tmp/work
# Only continue if previous succeeds
apt update && apt upgrade -y
# Fallback on failure
ping -c1 host1 || ping -c1 host2
# Chain with both
./build.sh && echo "Success" || echo "Failed"

OperatorPurpose
>Redirect stdout to file (overwrite)
>>Redirect stdout to file (append)
2>Redirect stderr to file
2>>Redirect stderr to file (append)
&>Redirect both stdout and stderr to file
2>&1Redirect stderr to wherever stdout is going
< fileUse file as stdin
Terminal window
# Save command output to file
echo "hello" > output.txt
# Append to a log
echo "entry" >> log.txt
# Discard errors
find / -name "*.conf" 2>/dev/null
# Capture everything
./script.sh &> all-output.txt
# Redirect stderr to stdout then pipe both
./script.sh 2>&1 | grep "error"

OperatorPurpose
&Run command in background
Ctrl+ZSuspend foreground job
bgResume suspended job in background
fgBring background job to foreground
jobsList background jobs
nohupRun command immune to hangups (survives logout)
disownDetach a running job from the shell
Terminal window
# Run in background
./long-task.sh &
# Check background jobs
jobs -l
# Survive logout
nohup ./server.sh &

SyntaxPurpose
(A; B)Run A and B in a subshell (own environment)
{ A; B; }Run A and B in the current shell (grouped)
$(command)Command substitution — capture output
`command`Command substitution (legacy syntax)
Terminal window
# Subshell — cd doesn't affect parent
(cd /tmp && ls)
# Grouping — redirect output of multiple commands
{ echo "header"; cat data.txt; } > combined.txt
# Command substitution
files=$(ls *.txt)
echo "Today is $(date +%Y-%m-%d)"

SyntaxPurpose
[[ condition ]]Bash conditional test
$?Exit code of last command (0 = success)
test expressionPOSIX conditional test
Terminal window
# Check if file exists
[[ -f /etc/passwd ]] && echo "exists"
# Check exit code
grep -q "root" /etc/passwd
echo $? # 0 if found, 1 if not
# String comparison
[[ "$USER" == "root" ]] && echo "running as root"

VariableMeaning
$?Exit code of last command
$$Current shell’s PID
$!PID of last background command
$0Name of the script
$1$9Positional arguments
$#Number of arguments
$@All arguments (as separate words)
$*All arguments (as one word)