Getting Started with tee - Splitting Command Output
What is tee?
|) to chain commands, but I want to save the intermediate results too. Is there a way to do that?tee is for! Think of it like a T-shaped pipe fitting — it splits the output in two directions at once.When you use a pipe, output flows from one command to the next and disappears. With tee, you can save the output to a file while still passing it downstream.
Normal pipe:
CommandA → CommandB (what's in the middle is gone)
With tee:
CommandA → tee ──→ saved to file
↓
flows to CommandB tooWhere the name comes from
The capital letter "T" — one input, two outputs. Same idea as a T-junction in plumbing.
Basic Usage
tee filename in the middle of your pipeline!command | tee filename
Example: display ls -la output on screen and save it to list.txt
ls -la | tee list.txt
Both happen at the same time — the output appears on screen and gets written to list.txt.
What tee gives you
- Screen output: uninterrupted, as if tee wasn't there
- File save: happens simultaneously
tee vs > Redirect
command | tee file different from command > file?>, the output goes only to the file — nothing shows on screen. With tee, you get both.| Method | Screen output | File save |
|---|---|---|
command |
yes | no |
command > file |
no | yes |
command | tee file |
yes | yes |
Use > when you just want to store output silently. Use tee when you want to watch it happen and save it at the same time.
Saving Logs While Watching Output
make install 2>&1 | tee install.log
2>&1 redirects stderr (error messages) into the same stream as stdout, so both end up in the log file.
What 2>&1 means
1= stdout (normal output)2= stderr (error messages)2>&1= merge stderr into stdout
Without this, error messages go only to the terminal and never reach tee.
The -a Flag: Append Instead of Overwrite
-a if you want to append instead.command | tee -a filename
Example: accumulate run timestamps in one log file
date | tee -a run.log date | tee -a run.log cat run.log
Mon Jun 1 03:00:00 UTC 2026 Mon Jun 1 03:00:05 UTC 2026
Without -a, every tee call overwrites the file from scratch. Use -a whenever you want to preserve previous entries.
Writing to Multiple Files
command | tee file1 file2
Example: save to both /tmp/result.txt and ~/backup.txt
ls -la | tee /tmp/result.txt ~/backup.txt
All listed files receive the same content. You can list as many as you need.
The sudo tee Pattern
sudo tee shines. It's a classic Linux pattern that trips up a lot of beginners.You might expect this to work — but it doesn't:
# This fails sudo echo "127.0.0.1 example.local" >> /etc/hosts
Why sudo echo > file fails
sudo only applies to the echo command itself. The >> redirect is processed by the shell, which runs as your regular user. The shell tries to open /etc/hosts for writing before sudo echo even runs — and gets denied.
The correct approach is sudo tee:
echo "127.0.0.1 example.local" | sudo tee -a /etc/hosts
Here, echo runs as your user (fine — it just writes to stdout), and sudo tee runs as root and does the privileged write.
tee prints the content to the terminal as well. To suppress that output, redirect stdout to /dev/null:
echo "127.0.0.1 example.local" | sudo tee -a /etc/hosts > /dev/null
Always back up before editing system files
sudo cp /etc/hosts /etc/hosts.bak
Mistakes in /etc/hosts or similar files can break your system's network resolution.
Debugging Pipelines
tee at any point to snapshot the data at that stage — without breaking the flow.cat access.log | grep "ERROR" | tee /tmp/errors.txt | sort | uniq -c
What this does:
grep "ERROR"filters the logteesaves those matching lines to/tmp/errors.txtsort | uniq -ccounts occurrences
You can then inspect /tmp/errors.txt separately to see exactly what went into the sorting step — useful when the final output looks unexpected.
For deep pipeline debugging, add multiple tee calls at different stages:
cat data.txt | step1 | tee /tmp/stage1.txt | step2 | tee /tmp/stage2.txt | step3
Compare the stage files to isolate exactly where things go wrong.
Common Patterns at a Glance
sudo tee, you'll use it all the time for config file edits. It's one of those small commands that shows up everywhere in real Linux work.| Use case | Command |
|---|---|
| Display and save at the same time | command | tee file.txt |
| Append without overwriting | command | tee -a file.txt |
| Save to multiple files | command | tee file1 file2 |
| Write to a root-owned file | echo "..." | sudo tee -a /etc/hosts |
| Snapshot pipeline midpoint | cmd1 | tee /tmp/debug.txt | cmd2 |
| Capture all output including error | command 2>&1 | tee output.log |