Reading — step 1 of 7
Learn
~3 min readI/O and Iteration
Bash's redirection isn't just > and <. The full file descriptor model lets you route any stream anywhere. Bash Cookbook treats this as essential for production scripts.
Standard streams
Every process has three open by default:
- fd 0 (stdin) — input
- fd 1 (stdout) — normal output
- fd 2 (stderr) — errors
echo "hello" # writes to fd 1 (stdout)
echo "oops" >&2 # writes to fd 2 (stderr)
read line # reads from fd 0 (stdin)
Basic redirection
cmd > out.txt # stdout to file (truncate)
cmd >> out.txt # stdout to file (append)
cmd 2> err.txt # stderr to file
cmd < in.txt # stdin from file
cmd > out.txt 2> err.txt # split stdout and stderr
Combining streams
cmd > all.txt 2>&1 # stderr to stdout, both to file
# Common shortcut:
cmd &> all.txt # bash-only: both to file
cmd >& all.txt # alternative form
cmd 2>&1 | grep foo # pipe BOTH stdout and stderr to grep
cmd 2>&1 > out.txt # WRONG order — stderr to terminal, stdout to file
cmd > out.txt 2>&1 # CORRECT — both to file
Order matters. 2>&1 means "redirect fd 2 to whatever fd 1 currently points to" — so it must come AFTER > out.txt.
Discarding output
cmd > /dev/null # discard stdout
cmd 2> /dev/null # discard stderr
cmd &> /dev/null # discard everything
Use this when you only care about the exit status:
if command -v git &> /dev/null; then
echo "git is installed"
fi
Here-documents and here-strings
# Here-doc — multi-line literal:
cat <<EOF
Line 1
Line 2
EOF
# Here-doc with interpolation:
name="Ada"
cat <<EOF
Hello, $name
EOF
# Here-doc literal (no interpolation — quote the marker):
cat <<'EOF'
No $variable expansion here
EOF
# Here-string — single-line:
grep foo <<< "hello world foo bar"
Here-docs are great for embedded scripts, SQL, JSON. Here-strings replace echo "..." |.
Custom file descriptors
# Open fd 3 for writing to a log:
exec 3> /var/log/myscript.log
echo "info message" >&3
echo "error" >&2
exec 3>&- # close fd 3
Advanced — useful for scripts with multiple output channels (audit log, error log, normal output).
tee — split a stream
cmd | tee output.txt # write to file AND stdout
cmd | tee -a output.txt # append (don't truncate)
cmd 2>&1 | tee -a log.txt # log everything
Useful for capturing output while still seeing it in the terminal.
Common mistakes
2>&1BEFORE>file— wrong order. stderr ends up at the terminal.- Confusing
>with>>—>truncates;>>appends. Mistakes wipe files. - Quoting variables in here-docs —
<<EOFinterpolates;<<'EOF'(quoted) is literal. - Using
cat file | cmd— useless cat. Usecmd < fileor< file cmd. - Forgetting that exit status of a pipeline is the LAST command — without
set -o pipefail, errors mid-pipeline go silent.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…