Stage 3 · Build
Shell Scripting & Automation
Pipes & Redirection
stdin, stdout, stderr, tee, process substitution, and pipefail behavior.
File Descriptors
Every process has three standard file descriptors: stdin (0), stdout (1), and stderr (2). Understanding these is essential for controlling data flow in shell scripts.
| FD | Name | Purpose | Default |
|---|---|---|---|
| 0 | stdin | Standard input | Keyboard |
| 1 | stdout | Standard output | Terminal |
| 2 | stderr | Standard error | Terminal |
Redirection Operators
# Output redirection
echo "hello" > file.txt # Overwrite
echo "world" >> file.txt # Append
# Input redirection
sort < unsorted.txt
wc -l < /etc/passwd
# Redirect both stdout and stderr
command > file.txt 2>&1 # Traditional
command &> file.txt # Bash shorthand
# Redirect stderr only
command 2> errors.log
# Discard output
command > /dev/null
command &> /dev/null
# Redirect to /dev/null selectively
command 2>/dev/null # Discard stderr only
command >/dev/null 2>&1 # Discard everything> overwrites, >> appends. 2>&1 redirects stderr to stdout. &> redirects both stdout and stderr.
stderr Handling
# Log both stdout and stderr, but only show stderr
command > output.log 2>&1 | tee /dev/tty
# Separate stdout and stderr into different files
command > stdout.log 2> stderr.log
# Redirect stderr to stdout, then pipe
command 2>&1 | grep "error"
# Only pipe stderr
command 2>&1 >/dev/null | grep "error"
# Append stderr to a log file
command 2>> error.log
# Redirect specific fd
exec 3> custom.log
echo "to custom log" >&3
exec 3>&-stderr is typically unbuffered and goes directly to the terminal. Redirect it to capture error messages while letting stdout continue to the pipeline.
tee: Split Output
# Split output to file and terminal
echo "hello" | tee output.txt
# Output: hello (displayed)
# Also: written to output.txt
# Append mode
echo "more" | tee -a output.txt
# Pipe and log
command | tee output.log | grep "pattern"
# Write to multiple files
command | tee file1.txt file2.txt file3.txt
# Combine with stderr
command 2>&1 | tee output.log
# Write to a file with sudo (when you don't own the file)
command | sudo tee /etc/config > /dev/nulltee reads from stdin and writes to both stdout and files. It is the standard tool for logging pipeline output while still processing it.
Process Substitution
# <() creates a temp file descriptor with command output
# Compare two command outputs
diff <(ls /dir1) <(ls /dir2)
# Feed a while loop from a pipe
while read -r line; do
echo "Processing: $line"
done < <(find /var/log -name "*.log" -mtime -1)
# Parallel processing
while read -r host; do
ssh "$host" uptime &
done < <(cat hosts.txt)
wait
# Combine with here-strings
diff <(sort file1.txt) <(sort file2.txt)
# Two-way process substitution (Bash 4.1+)
coproc myprocess { command; }
echo "input" >&${COPROC[1]}
read -r output <&${COPROC[0]}Process substitution creates anonymous pipes that act like files. <() for input, >() for output. Avoids temp files and subshells.
pipefail Behavior
# Without pipefail
set +o pipefail
false | true
echo $? # 0 (last command succeeded)
# With pipefail
set -o pipefail
false | true
echo $? # 1 (any command in pipe failed)
# Real-world example
command1 | command2 | command3
# Without pipefail: only command3's exit code matters
# With pipefail: the first failed command's exit code is returned
# This is why set -euo pipefail is critical
# It catches failures in pipelines that would otherwise be silent
# Override pipefail for a single pipeline
set +o pipefail
false | true
echo $? # 0 (pipefail disabled)
set -o pipefailpipefail makes pipelines return the exit code of the last failing command. Without it, only the last command's exit code is checked, hiding failures in earlier commands.
diff <(cmd1) <(cmd2) is cleaner than saving output to temp files. It works with any commands, not just file-generating ones.
Without pipefail, command1 | command2 succeeds even if command1 fails. This causes data loss and incorrect behavior. Always enable pipefail in scripts.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.