tee Command Linux: Write Output to Multiple Destinations Simultaneously

August 25, 2025

The tee command in Linux is a powerful utility that reads from standard input and writes the output to both standard output and one or more files simultaneously. Named after the T-shaped pipe fitting in plumbing, it allows you to “split” the flow of data, making it an essential tool for system administrators, developers, and power users who need to capture command output while still viewing it on the terminal.

Understanding the tee Command Syntax

The basic syntax of the tee command is straightforward:

command | tee [OPTIONS] [FILE...]

Where:

  • command: Any Linux command whose output you want to capture
  • OPTIONS: Various flags to modify tee’s behavior
  • FILE: One or more files where the output will be written

Basic tee Command Usage

Simple Output Redirection

Let’s start with a basic example of capturing command output:

ls -la | tee file_list.txt

Output:

total 24
drwxr-xr-x 3 user user 4096 Aug 25 05:25 .
drwxr-xr-x 5 user user 4096 Aug 25 05:20 ..
-rw-r--r-- 1 user user  220 Aug 25 05:25 .bash_logout
-rw-r--r-- 1 user user 3771 Aug 25 05:25 .bashrc
-rw-r--r-- 1 user user  807 Aug 25 05:25 .profile
-rw-r--r-- 1 user user    0 Aug 25 05:25 file_list.txt

This command displays the directory listing on your terminal while simultaneously writing the same output to file_list.txt.

Writing to Multiple Files

One of tee’s most powerful features is writing to multiple files at once:

date | tee current_date.txt backup_date.txt log_date.txt

Output:

Mon Aug 25 05:25:30 IST 2025

This creates three files, each containing the current date and time, while also displaying it on the terminal.

Essential tee Command Options

Append Mode (-a)

By default, tee overwrites existing files. Use the -a flag to append instead:

echo "First entry" | tee log.txt
echo "Second entry" | tee -a log.txt
echo "Third entry" | tee -a log.txt

Contents of log.txt:

First entry
Second entry
Third entry

Ignore Interrupts (-i)

The -i option makes tee ignore interrupt signals, useful for long-running processes:

ping google.com | tee -i ping_results.txt

This ensures that even if you press Ctrl+C, the output captured so far remains in the file.

Advanced tee Command Examples

Combining with sudo for System Files

When you need to write to system files that require root privileges:

echo "127.0.0.1 test.local" | sudo tee -a /etc/hosts

This appends a new host entry to the system’s hosts file, which is a common administrative task.

Logging Command Output with Timestamps

Create detailed logs with timestamps:

ps aux | tee >(cat > "processes_$(date +%Y%m%d_%H%M%S).log")

This creates a timestamped file containing the current process list.

Real-time Log Monitoring

Monitor log files while saving specific entries:

tail -f /var/log/syslog | tee important_events.log

This displays real-time system logs while capturing them to a separate file for later analysis.

Practical Use Cases and Scenarios

System Administration Tasks

Backup Operations with Logging:

rsync -av /home/user/documents/ /backup/documents/ | tee backup.log

This performs a backup while maintaining a detailed log of the operation.

System Updates with Documentation:

sudo apt update && sudo apt upgrade -y | tee system_update.log

Development and Debugging

Compilation Output Capture:

make build 2>&1 | tee build.log

This captures both standard output and error messages from the build process.

Test Results Documentation:

pytest tests/ -v | tee test_results.txt

Data Processing Pipelines

Processing Large Datasets:

cat large_dataset.csv | grep "error" | tee error_entries.csv filtered_output.csv

This filters data while saving results to multiple files for different purposes.

Creative tee Command Combinations

Multiple Processing Streams

Use process substitution for complex data flow:

cat access.log | tee >(grep "404" > errors_404.log) >(grep "200" > success_200.log)

This splits web server logs into separate files based on HTTP status codes.

Conditional Output Routing

Combine with conditional statements:

if command_status; then
    echo "Success" | tee success.log
else
    echo "Failed" | tee error.log
fi

Performance Considerations

Memory Usage

When processing large amounts of data, tee uses minimal memory as it operates as a stream processor:

find / -name "*.log" 2>/dev/null | tee large_file_list.txt

This command can process millions of files without significant memory overhead.

Disk I/O Optimization

For high-throughput scenarios, consider using unbuffered output:

command | stdbuf -o0 tee output.txt

Error Handling and Troubleshooting

Capturing Error Messages

Redirect both stdout and stderr through tee:

command 2>&1 | tee complete_output.log

Handling Permission Issues

When tee cannot write to a file due to permissions:

echo "data" | tee /path/to/restricted/file.txt
# Error: Permission denied

# Solution:
echo "data" | sudo tee /path/to/restricted/file.txt

Integration with Other Linux Commands

Combining with awk and sed

ps aux | awk '{print $1, $11}' | tee user_commands.txt

This extracts specific columns from process output and saves them.

Working with xargs

find . -name "*.txt" | tee file_list.txt | xargs wc -l

This creates a file list while simultaneously counting lines in each file.

Best Practices and Tips

File Naming Conventions

Use descriptive, timestamped filenames:

command | tee "output_$(hostname)_$(date +%Y%m%d).log"

Combining with Compression

For large outputs, compress on-the-fly:

command | tee >(gzip > output.gz)

Rotating Log Files

Implement simple log rotation:

command | tee >(split -b 1M - "logfile_part_")

Common Pitfalls and Solutions

Overwriting Important Files

Problem: Accidentally overwriting existing files

Solution: Always use the -a flag when appending or check file existence first:

[ ! -f important.txt ] && command | tee important.txt || command | tee -a important.txt

Missing Error Output

Problem: Error messages not captured

Solution: Redirect stderr to stdout before piping:

command 2>&1 | tee complete_log.txt

Conclusion

The tee command is an indispensable tool in the Linux command-line arsenal, offering elegant solutions for output management and logging. Its ability to split data streams makes it perfect for scenarios where you need to monitor processes in real-time while maintaining permanent records. Whether you’re performing system administration tasks, debugging applications, or processing data pipelines, mastering tee will significantly enhance your command-line productivity.

By understanding its various options and creative applications, you can build more robust scripts and workflows that provide better visibility into your system operations. Remember to consider file permissions, use appropriate flags for your use case, and combine tee with other commands to create powerful data processing pipelines.