Command Line
File Processing
Stdout
Output Redirection
Scripting

How to redirect output to a file and stdout

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The tee command in Unix/Linux reads from standard input and writes to both standard output and one or more files simultaneously. This is essential when you want to see command output in the terminal while also saving it to a log file. Without tee, you can only redirect to a file (>) or display on screen, but not both at once.

Basic Usage with tee

bash
1# Display output AND save to file
2command | tee output.txt
3
4# Example
5ls -la | tee listing.txt
6# Shows the directory listing on screen AND saves it to listing.txt

Append Instead of Overwrite

By default, tee overwrites the file. Use -a to append:

bash
1# Overwrite (default)
2echo "first line" | tee output.txt
3
4# Append to existing file
5echo "second line" | tee -a output.txt
6
7# output.txt now contains both lines

Write to Multiple Files

tee can write to multiple files simultaneously:

bash
1command | tee file1.txt file2.txt file3.txt
2
3# Example: log to both a timestamped file and a latest-run file
4./build.sh | tee build-$(date +%Y%m%d).log build-latest.log

Redirecting Both stdout and stderr

tee only captures stdout by default. To capture stderr too:

bash
1# Method 1: Redirect stderr to stdout first, then tee
2command 2>&1 | tee output.txt
3
4# Method 2: Bash process substitution (captures both separately)
5command > >(tee stdout.txt) 2> >(tee stderr.txt >&2)
6
7# Method 3: Pipe both streams but keep stderr on screen too
8command 2>&1 | tee combined.txt

Explanation of 2>&1

bash
1# File descriptor 1 = stdout
2# File descriptor 2 = stderr
3# 2>&1 means "redirect stderr (2) to wherever stdout (1) is going"
4
5# Order matters:
6command 2>&1 | tee output.txt    # Correct: stderr merged before pipe
7command | tee output.txt 2>&1    # Wrong: only stdout goes through tee

Redirect Only stderr

bash
1# Send stderr to file while keeping stdout on screen
2command 2> error.log
3
4# Send stderr to file AND screen, stdout only on screen
5command 2> >(tee error.log >&2)

Using tee with sudo

Write to a file that requires root permissions:

bash
1# This fails — redirect runs as your user, not root
2sudo echo "new line" > /etc/config  # Permission denied
3
4# This works — tee runs as root
5echo "new line" | sudo tee /etc/config
6
7# Append with sudo
8echo "new line" | sudo tee -a /etc/config
9
10# Suppress terminal output (only write to file)
11echo "new line" | sudo tee /etc/config > /dev/null

Suppress tee's Terminal Output

If you only want the file and not the screen output:

bash
# Discard tee's stdout, keep only the file
command | tee output.txt > /dev/null

Practical Examples

Build Logs

bash
1# Save build output while watching it live
2make 2>&1 | tee build.log
3
4# With timestamp
5make 2>&1 | tee "build-$(date +%Y%m%d-%H%M%S).log"

Long-Running Scripts

bash
1# Monitor and log a deployment
2./deploy.sh 2>&1 | tee -a deploy.log
3
4# Run tests with live output and log
5pytest -v 2>&1 | tee test-results.txt

Pipeline Debugging

Inspect intermediate data in a pipeline:

bash
1# See what grep produces before passing to awk
2cat access.log | grep "ERROR" | tee /dev/stderr | awk '{print $1}' | sort | uniq -c
3
4# /dev/stderr shows grep output on screen without disrupting the pipeline

SSH Session Logging

bash
# Log an entire SSH session
ssh user@server 2>&1 | tee session.log

Alternatives to tee

Script Command (Record Full Sessions)

bash
script output.txt
# Everything you type and see is recorded
exit  # Stop recording

Process Substitution (Bash)

bash
1# Write to a file using process substitution (no pipe needed)
2command > >(tee output.txt)
3
4# Separate stdout and stderr to different files
5command > >(tee stdout.log) 2> >(tee stderr.log >&2)

Redirecting in Background Scripts

bash
1# Redirect all output of a script to both file and stdout
2exec > >(tee -a script.log) 2>&1
3
4echo "This goes to screen and script.log"
5ls /nonexistent  # Errors also go to both

Comparison of Redirect Methods

MethodScreenFileAppendstderr
> fileNoYesNoNo
>> fileNoYesYesNo
`\tee file`YesYesNoNo
`\tee -a file`YesYesYesNo
`2>&1 \tee file`YesYesNoYes
> >(tee file) 2>&1YesYesNoYes

Common Pitfalls

  • Buffering: Output piped through tee may be buffered, causing delayed display. Use unbuffer command | tee file (from expect package) or stdbuf -oL command | tee file to force line-buffered output.
  • Exit codes: In a pipeline command | tee file, the exit code is from tee (usually 0), not from command. Use set -o pipefail in bash to get the first non-zero exit code, or check ${PIPESTATUS[0]}.
  • File permissions: tee creates files with your user's permissions. Use sudo tee to write to root-owned files, not sudo command > file (the redirect runs as your user).
  • Binary data: tee is designed for text. Binary data piped through tee may be corrupted on some systems due to newline translation.
  • Disk space: Forgetting -a (append) overwrites the file each time. Conversely, always appending without rotation can fill up the disk.

Summary

  • Use command | tee file to display output on screen and save to a file simultaneously
  • Use tee -a file to append instead of overwrite
  • Use command 2>&1 | tee file to capture both stdout and stderr
  • Use echo "text" | sudo tee /path/to/file to write to root-owned files
  • Use stdbuf -oL or unbuffer to fix buffering issues with piped output

Course illustration
Course illustration

All Rights Reserved.