File Descriptor
From File Descriptor Image
Go to text →
From Fundumentals
Go to text →
File Descriptors - Fundamentals
What are File Descriptors?
File descriptors are non-negative integers that represent open files or input/output channels in Unix-like systems. Every process starts with three standard file descriptors:
- 0 = stdin (standard input)
- 1 = stdout (standard output)
- 2 = stderr (standard error)
Basic Redirection
# Redirect stdout to a file
echo "Hello" > output.txt # Same as: echo "Hello" 1> output.txt
# Redirect stdin from a file
cat < input.txt # Same as: cat 0< input.txt
# Redirect stderr to a file
ls /nonexistent 2> errors.txt
# Append to a file instead of overwriting
echo "More text" >> output.txt
Testing File Descriptors
Use the -t
test to check if a file descriptor is connected to a terminal:
# Check if stdout is a terminal
if [ -t 1 ]; then
echo "Output is going to terminal"
else
echo "Output is redirected/piped"
fi
# Check stdin
[ -t 0 ] && echo "Input is from terminal"
# Check stderr
[ -t 2 ] && echo "Errors go to terminal"
More on this in Detecting Output Destination in CLI Programs
From Intermediate
Go to text →
File Descriptors - Intermediate
Combining and Duplicating Streams
The &
Notation
The &
in redirections means "file descriptor":
# Redirect stderr to wherever stdout is going
command 2>&1
# Shorthand: redirect both stdout and stderr to file
command &> output.txt # Same as: command > output.txt 2>&1
command &>> output.txt # Append version
Order Matters!
# WRONG: stderr still goes to terminal
command > file.txt 2>&1 # Correct order
command 2>&1 > file.txt # WRONG: stderr goes to original stdout
Common Patterns
Silencing Output
# Discard all output
command > /dev/null 2>&1
# Discard only errors
command 2> /dev/null
# Discard output but keep errors
command > /dev/null
Logging Patterns
#!/bin/bash
# log-wrapper.sh - Log all output while still displaying it
# Log both stdout and stderr to file while showing on screen
./mycommand 2>&1 | tee output.log
# Separate error logging
./mycommand 2> >(tee -a error.log >&2) | tee -a output.log
Conditional Output
# verbose.sh - Control output verbosity
VERBOSE=${VERBOSE:-0}
debug() {
[ "$VERBOSE" -eq 1 ] && echo "[DEBUG] $*" >&2
}
info() {
echo "[INFO] $*"
}
error() {
echo "[ERROR] $*" >&2
}
# Usage
debug "This only shows if VERBOSE=1"
info "This always shows"
error "This goes to stderr"
Reading and Writing Simultaneously
# Process a file in-place (careful!)
while IFS= read -r line; do
echo "PROCESSED: $line"
done < input.txt > temp.txt && mv temp.txt input.txt
Children
Backlinks