Bash Cheatsheet
I/O Redirection
Use this Bash reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Standard File Descriptors
| FD | Name | Default |
|---|---|---|
0 | stdin | keyboard |
1 | stdout | terminal |
2 | stderr | terminal |
Output Redirection
cmd > file # redirect stdout to file (overwrite) cmd >> file # redirect stdout to file (append) cmd 2> file # redirect stderr to file (overwrite) cmd 2>> file # redirect stderr to file (append) cmd &> file # redirect both stdout and stderr (Bash 4+) cmd &>> file # append both stdout and stderr (Bash 4+) cmd > file 2>&1 # redirect stdout to file, then stderr to stdout (POSIX) cmd 2>&1 > file # WRONG ORDER: stderr goes to terminal, stdout to file cmd > /dev/null # discard stdout cmd 2> /dev/null # discard stderr cmd &> /dev/null # discard all output
Input Redirection
cmd < file # redirect file to stdin cmd < file > outfile # redirect both in and out cmd <<< "string" # here-string: redirect string to stdin grep "foo" <<< "$variable" # Here-document: multi-line stdin cat <<EOF line 1 line 2 with $var expansion EOF # Quoted heredoc: no expansion cat <<'EOF' literal $var, no $(expansion) EOF # Strip leading tabs (not spaces) with <<- cat <<-EOF indented content more content EOF
File Descriptor Manipulation
# Duplicate FD cmd 2>&1 # fd 2 (stderr) → same as fd 1 (stdout) cmd 1>&2 # fd 1 (stdout) → same as fd 2 (stderr) cmd >&2 # shorthand: stdout → stderr # Open a file to a custom FD exec 3> output.txt # open output.txt on fd 3 for writing echo "hello" >&3 # write to fd 3 exec 3>&- # close fd 3 exec 4< input.txt # open input.txt on fd 4 for reading read -u 4 line # read from fd 4 exec 4<&- # close fd 4 # Save and restore fd 1 exec 3>&1 # save stdout to fd 3 exec 1> log.txt # redirect stdout to log echo "this goes to log" exec 1>&3 # restore stdout exec 3>&- # close fd 3 # Read-write fd exec 5<> /tmp/scratch # open for both reading and writing
/dev Special Files
/dev/null # discard reads always return EOF; writes discard /dev/zero # reads return infinite null bytes /dev/random # cryptographically secure random bytes (blocks) /dev/urandom # non-blocking random bytes /dev/stdin # fd 0 /dev/stdout # fd 1 /dev/stderr # fd 2 /dev/fd/N # alias for file descriptor N /dev/tcp/host/port # (Bash built-in) open TCP connection /dev/udp/host/port # (Bash built-in) open UDP connection # TCP via /dev/tcp exec 3<>/dev/tcp/example.com/80 echo -e "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n" >&3 cat <&3 exec 3>&-
Pipes
cmd1 | cmd2 # pipe stdout of cmd1 to stdin of cmd2 cmd1 | cmd2 | cmd3 # pipeline chain cmd1 |& cmd2 # pipe stdout+stderr of cmd1 (Bash 4+) cmd1 2>&1 | cmd2 # POSIX equivalent of |& # Pipeline exit status echo $? # exit status of last command in pipeline echo ${PIPESTATUS[@]} # array of exit statuses of each command (Bash) set -o pipefail # make pipeline fail if any command fails # Named pipe (FIFO) mkfifo /tmp/mypipe cmd1 > /tmp/mypipe & cmd2 < /tmp/mypipe rm /tmp/mypipe
Process Substitution
# Treat command output as a file diff <(sort file1.txt) <(sort file2.txt) comm <(sort list1) <(sort list2) while IFS= read -r line; do echo "$line" done < <(find . -name "*.sh") # Write to a command as if it's a file tee >(gzip > out.gz) > out.txt # write to both gzip and a file tee >(cmd1) >(cmd2) > /dev/null # fan-out to multiple commands
tee — Split Output
cmd | tee file.txt # stdout goes to both terminal AND file cmd | tee -a file.txt # append to file cmd | tee file1.txt file2.txt # write to multiple files cmd | tee /dev/stderr | cmd2 # tee to stderr while piping to cmd2 cmd | tee >(cmd_a) >(cmd_b) # fan-out via process substitution
Redirecting Multiple Commands
# Redirect entire block { echo "first" echo "second" } > output.txt # Redirect loop output for i in {1..5}; do echo "line $i" done > output.txt # Redirect function output myfunc() { echo "hello"; echo "world"; } myfunc > out.txt 2>&1 # exec to redirect all subsequent output exec > output.log 2>&1 # all output for rest of script goes to log exec 2> error.log # redirect only stderr
Logging Patterns
# Log stdout and stderr separately cmd > out.log 2> err.log # Log stderr only, show stdout cmd 2> err.log # Show output AND save to log cmd 2>&1 | tee output.log # Timestamp each line cmd | while IFS= read -r line; do echo "[$(date '+%H:%M:%S')] $line" done | tee -a app.log # Append with separator echo "--- $(date) ---" >> app.log cmd >> app.log 2>&1
Here Strings and Heredoc Advanced
# Feed heredoc to a command mysql -u user -ppass dbname <<SQL SELECT * FROM users WHERE active = 1; DROP TABLE tmp_cache; SQL # Heredoc in a function usage() { cat <<EOF Usage: $0 [OPTIONS] <file> Options: -h show this help -v verbose EOF } # Variable in heredoc name="Alice" cat <<EOF Dear $name, Your account is ready. EOF # Literal (no expansion) cat <<'SCRIPT' #!/bin/bash echo "I contain $literal variables" SCRIPT
/proc and Special Redirects
# Read a file without spawning cat content=$(<file.txt) # fast: reads file content into variable # Write without echo (slightly faster) printf '%s\n' "content" > file.txt # Redirect to multiple files at once (append) { cmd1; cmd2; } | tee -a log1.txt log2.txt > /dev/null