How to redirect command output to both a file and stdout in bash
In bash, calling foo displays any output from that command on the stdout.
Calling foo > output redirects any output from that command to the specified file (in this case ‘output’).
Is there a way to redirect output to a file and simultaneously display it on stdout?
To redirect command output to both a file and stdout simultaneously in bash, you can use the tee command. The most common approach is to pipe your command’s output to tee, which will then write to both the terminal and the specified file. For example: command | tee filename redirects stdout to both places, while command 2>&1 | tee filename redirects both stdout and stderr to both destinations.
Contents
- Using the tee Command
- Redirecting Both stdout and stderr
- Advanced Techniques
- Script-Level Redirection
- Common Use Cases
- Troubleshooting Tips
Using the tee Command
The tee command is specifically designed for this purpose. It reads from standard input and writes to both standard output and one or more files simultaneously.
Basic Syntax
command | tee filename
Example:
ls -la | tee output.txt
This command will list directory contents and display them in the terminal while also writing the same output to output.txt.
Key tee Options:
-aor--append: Append to the file instead of overwriting it-ior--ignore-interrupts: Ignore interrupt signals
Example with append:
long_running_process | tee -a app.log
Redirecting Both stdout and stderr
To redirect both standard output and standard error to both the terminal and a file, you need to combine the file descriptors first.
Method 1: Combine stderr to stdout first
command 2>&1 | tee filename
Example:
find . -name "*.txt" 2>&1 | tee search_results.txt
Method 2: Use the |& shorthand (Bash 4+)
command |& tee filename
Example:
curl -s https://example.com |& tee curl_output.log
Method 3: Using process substitution for separate handling
(command > >(tee stdout.log)) 2> >(tee stderr.log)
Advanced Techniques
Process Substitution for Complex Scenarios
Process substitution >(...) creates a FIFO that can be read by one command and written to by another.
Example: Separate stdout and stderr to different files while also showing both on terminal
(echo 'ok'; echo 'error' >&2) 2> >(tee err.log) > >(tee out.log) | tee all.log
Multiple Files with tee
You can write to multiple files simultaneously:
command | tee file1.txt file2.txt file3.txt
Conditional Redirection
You can make redirection conditional based on whether output is going to a terminal:
if [ -t 1 ]; then
command | tee "$logfile"
else
command > "$logfile"
fi
Script-Level Redirection
For entire scripts, you can use exec to redirect all output:
Redirect all output (stdout and stderr) for the entire script
#!/bin/bash
exec &> >(tee -a script.log)
echo "This goes to both terminal and log file"
some_command_with_errors
Conditional script-level redirection
#!/bin/bash
if [ -t 1 ]; then
exec &> >(tee -a "$logfile")
else
exec &> "$logfile"
fi
Common Use Cases
Logging Long-Running Processes
./long_running_script.sh | tee -a process.log
Development and Debugging
make 2>&1 | tee build.log
System Administration Tasks
sudo apt update 2>&1 | tee apt_update.log
Monitoring Commands
tail -f /var/log/syslog | tee -a monitor.log
Pipeline Processing
cat largefile.txt | grep "pattern" | tee filtered.txt | wc -l
Troubleshooting Tips
Common Issues and Solutions
Issue: Missing stderr output
Solution: Make sure to redirect stderr to stdout first: command 2>&1 | tee file
Issue: File permissions errors
Solution: Ensure you have write permissions to the target file/directory
Issue: Output appears delayed
Solution: Use tee -a instead of tee to avoid overwriting issues
Issue: Different behavior in scripts vs interactive shell
Solution: Use set -o pipefail to handle errors properly in pipelines
Performance Considerations
- For very high-volume output, consider using
tee -ato avoid file truncation issues - Multiple
teecommands can impact performance significantly - For production logging, consider dedicated logging tools
Conclusion
Key Takeaways
- The
teecommand is the primary tool for redirecting output to both file and stdout - Use
command 2>&1 | tee filenameto capture both stdout and stderr - Process substitution offers advanced capabilities for complex redirection scenarios
execcan redirect all output at the script level- Understanding file descriptors (1=stdout, 2=stderr) is crucial for proper redirection
Practical Recommendations
- For simple logging: Use
command | tee filename - For comprehensive logging: Use
command 2>&1 | tee filename - For scripts: Consider
exec &> >(tee -a logfile)for complete redirection - Always verify file permissions before redirecting to files
- Use
-aoption withteewhen you need to append to existing log files
Related Questions
- How to redirect only stderr to both file and terminal?
- Can I use tee with gzipped output?
- What’s the difference between
teeandtee -a? - How to handle color codes when using tee with log files?
For more advanced scenarios, consider exploring bash process substitution and advanced file descriptor manipulation techniques.
Sources
- Stack Overflow - How to redirect output to a file and stdout
- Server Fault - Capturing STDERR and STDOUT to a file using ‘tee’
- Linux Bash - tee: Redirect output to files and stdout
- Baeldung on Linux - Redirect Output of a Process to a File and Standard Streams
- Unix & Linux Stack Exchange - Using exec and tee to redirect logs
- Super User - How to redirect output to both a file and stdout
- Reddit - Command tee file tee stderr and stdout issue
- Linux Hint - Redirecting stderr Using the tee Command