How to redirect command output to both a file and stdout in Bash?
In Bash, calling foo displays any output from that command on 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?
You can redirect command output to both a file and stdout in Bash using the tee command. The tee command reads from standard input and writes to both standard output and one or more files simultaneously, making it perfect for this use case. For example, foo | tee output will display the output from foo on your terminal while also saving it to the ‘output’ file.
Contents
- Understanding Output Redirection
- Using the tee Command
- Advanced tee Usage
- Comparison with Alternative Methods
- Practical Examples
Understanding Output Redirection
In Bash, output redirection works by redirecting file descriptors. The three main standard streams are:
- stdout (file descriptor 1): Normal output from commands
- stderr (file descriptor 2): Error messages and diagnostics
- stdin (file descriptor 0): Input to commands
When you use > redirection like foo > output, you’re redirecting stdout (file descriptor 1) to the specified file. This is equivalent to 1> output, where the 1 explicitly specifies the stdout file descriptor.
The basic redirection operators include:
>- Overwrite file with output>>- Append output to file<- Read input from file
However, these operators only redirect output to one destination - either to a file or to stdout, but not both simultaneously.
Using the tee Command
The tee command is the standard solution for redirecting output to both stdout and a file. Its basic syntax is:
command | tee filename
For example:
ls -l | tee directory_listing.txt
This command will:
- Show the directory listing on your terminal (stdout)
- Save the same output to
directory_listing.txt
The tee command reads from standard input and writes to both standard output and the specified file(s).
Key Features of tee
- Simultaneous output: Works with multiple files using
-aflag - Append mode: Use
tee -a filenameto append instead of overwrite - Multiple files: Can write to several files at once:
command | tee file1.txt file2.txt file3.txt - Preserves output: Maintains the original output stream for further piping
Here are some common tee usage patterns:
# Basic tee usage
echo "Hello World" | tee hello.txt
# Append to file instead of overwrite
echo "Another line" | tee -a hello.txt
# Write to multiple files
ls -l | tee listing.txt backup_listing.txt
# Chain with other commands
ls -l | grep ".txt" | tee text_files.txt | wc -l
Advanced tee Usage
Handling Both stdout and stderr
If you need to capture both standard output and error messages while still displaying them, you can combine redirection with tee:
# Redirect both stdout and stderr to tee
command 2>&1 | tee output.log
# Or using the &> shorthand
command &> output.log | tee output.log
Using tee in Scripts
In shell scripts, tee is particularly useful for logging while maintaining interactive output:
#!/bin/bash
echo "Starting process..."
echo "Processing data..." | tee process.log
echo "Completed successfully!" | tee -a process.log
tee with Process Substitution
You can use tee with process substitution for more complex scenarios:
# tee to multiple processes simultaneously
command | tee >(grep "error") >(grep "warning") error.log
Comparison with Alternative Methods
While tee is the most straightforward solution, there are alternative approaches with different characteristics:
1. Using Brace Expansion
{ foo; } 2>&1 | tee output
This captures the entire command output but requires grouping.
2. Using Subshells
(foo | tee output)
This runs the command in a subshell, which can be useful for scoping.
3. Using Script Redirection
You could create a wrapper script that duplicates output:
#!/bin/bash
"$@" | tee "$1"
However, these alternatives are generally more complex and less readable than using tee directly.
Practical Examples
System Monitoring
# Monitor system resources while logging
top -b | tee system_monitor.log
# Monitor log files in real-time
tail -f /var/log/syslog | tee -f live_syslog.log
Development and Testing
# Run tests while capturing output
npm test | tee test_results.txt
# Build process logging
make all | tee build.log
Data Processing
# Process CSV data while showing progress
cat large_file.csv | process_data | tee processed_data.csv
# Network monitoring while capturing packets
tcpdump -i eth0 | tee network_capture.pcap
Long-running Processes
# Backup process with progress indication
rsync -av /source/ /destination/ | tee backup.log
# Compilation output
make -j4 | tee compilation.log
The Linux Shell Commands and I/O Redirection guide provides additional context on how command | tee file.txt works as a “Display and save simultaneously” operation.
According to LinuxOpsys, understanding the file descriptor system is crucial for mastering redirection in Linux, where > is synonymous with 1> for stdout redirection.
Conclusion
- The tee command is the standard solution for redirecting output to both stdout and files in Bash, using the syntax
command | tee filename - tee offers flexibility with options like
-afor append mode and the ability to write to multiple files simultaneously - Unlike simple redirection, tee preserves the output stream for further piping while also saving to files
- For most use cases, tee provides the cleanest and most readable solution compared to alternatives like brace expansion or subshells
- Remember that tee handles only stdout by default - use
2>&1to capture stderr as well when needed
The next time you need to save command output while still seeing it on screen, reach for the tee command - it’s the perfect tool for this common Bash scenario.