Bash Input/Output Redirection
Bash provides powerful tools for controlling input and output streams. Understanding I/O redirection is essential for scripting and system administration.
Standard Streams
Bash has three standard streams:
- stdin (0): Standard input (keyboard by default)
- stdout (1): Standard output (terminal by default)
- stderr (2): Standard error (terminal by default)
Basic Redirection Operators
# Redirect stdout to a file (overwrite)
command > file.txt
# Redirect stdout to a file (append)
command >> file.txt
# Redirect stderr to a file
command 2> error.log
# Redirect both stdout and stderr to a file
command &> output.log
# Redirect stdout and stderr to separate files
command > output.log 2> error.log
Here Documents
A here document (heredoc) is a way to pass multiline input to a command:
cat << EOF
This is a multiline
text block that will be
passed to the cat command.
EOF
Here Strings
Here strings are a shorter alternative to here documents for single-line input:
grep "search" <<< "This string contains the search term"
Pipes
Pipes connect the stdout of one command to the stdin of another:
# Count the number of files in a directory
ls -1 | wc -l
# Find processes and filter results
ps aux | grep "nginx"
Advanced Redirection
# Redirect stderr to stdout
command 2>&1
# Redirect stdout to stderr
echo "Error message" 1>&2
# Discard output (send to /dev/null)
command > /dev/null
# Redirect stdout to file and also display it
command | tee output.txt
# Redirect stdout to file and append
command | tee -a output.txt
File Descriptors
You can create custom file descriptors for advanced I/O operations:
# Create a custom file descriptor
exec 3<> file.txt
# Read from descriptor 3
read -u 3 line
# Write to descriptor 3
echo "New content" >&3
# Close descriptor 3
exec 3>&-
Process Substitution
Process substitution allows you to use command output as if it were a file:
# Compare output of two commands
diff <(ls dir1) <(ls dir2)
# Feed output of multiple commands to another command
paste <(command1) <(command2) > output.txt
Practical Examples
# Log both output and errors with timestamp
command 2>&1 | while read line; do
echo "$(date '+%Y-%m-%d %H:%M:%S'): $line"
done >> logfile.txt
# Read file line by line
while read -r line; do
echo "Processing: $line"
done < input.txt
# Read from multiple files
while read -u 3 line1 && read -u 4 line2; do
echo "$line1 and $line2"
done 3< file1.txt 4< file2.txt
Common Pitfalls
- Forgetting that redirection order matters (
command 2>&1 >file
is different fromcommand >file 2>&1
) - Not quoting variables properly when they contain spaces or special characters
- Using pipes in loops can create subshells that limit variable scope
- Forgetting to close custom file descriptors