tee Command in Linux: Syntax, Options & Practical Examples

tee reads standard input and writes a copy to every named file while also sending the same bytes to standard output. Use it in pipelines when you want to save command output and still see it on the terminal.

Published

Updated

Read time 9 min read

Reviewed byDeepak Prasad

tee Command in Linux: Syntax, Options & Practical Examples
About tee reads standard input and writes a copy to every named file while also sending the same bytes to standard output. Use it in pipelines when you want to save command output and still see it on the terminal.
Tested on Ubuntu 25.04 (Plucky Puffin); tee (uutils coreutils) 0.2.2; kernel 7.0.0-27-generic
Package coreutils
Man page tee(1)
Privilege user (sudo when writing protected files)
Distros

All Linux distros that ship coreutils (GNU or uutils build).

Shell redirection (>, >>) covers the same file-write job without mirroring to the terminal.

tee — quick reference

Copy stdin to files and stdout

Read from a pipe or redirect and write the same stream to one or more files plus the terminal.

When to use Command
Write stdin to a file and print it on the terminal command | tee file
Append instead of overwriting the file command | tee -a file
Append using the long option name command | tee --append file
Write the same stream to several files at once command | tee file1 file2
Treat a file literally named - in the current directory command | tee ./-

Signals and write errors

Control how tee reacts to interrupts and failed writes on non-pipe outputs.

When to use Command
Keep running when the terminal sends interrupt signals (where supported) command | tee -i file
Same as above with the long name command | tee --ignore-interrupts file
Diagnose write errors on regular files (not pipes) command | tee -p file
Warn on any write error command | tee --output-error=warn file
Warn only on non-pipe write errors (default with -p on GNU builds) command | tee --output-error=warn-nopipe file
Exit immediately on any write error command | tee --output-error=exit file
Exit on non-pipe write errors command | tee --output-error=exit-nopipe file

Help and version

When to use Command
Show built-in usage text tee --help
Print the installed package version tee --version
Short version flag (uutils build on Ubuntu 25.04) tee -V

tee — command syntax

tee copies standard input to each FILE and to standard output. Synopsis from tee --help on Ubuntu 25.04 (tee uutils coreutils 0.2.2):

text
tee [OPTION]... [FILE]...

If a FILE is -, it refers to a file named - in the current directory (use ./- when you mean that path). tee does not edit system databases — it only writes bytes you pipe into it.


tee — command examples

Essential Save pipeline output and still see it on screen

Use tee when a command prints useful text but you also want a log file — for example after filtering with grep.

Run the command:

bash
PREFIX=tcs_
WORKDIR=/tmp/${PREFIX}lab
mkdir -p "$WORKDIR" && cd "$WORKDIR"
echo -e 'num 1\nother\nnum 2' > ${PREFIX}src.txt
grep num ${PREFIX}src.txt | tee ${PREFIX}grep.txt

Sample output:

text
num 1
num 2

Confirm the file holds the same lines:

bash
cat ${PREFIX}grep.txt

Sample output:

text
num 1
num 2

Without tee, redirecting with > would hide those lines from the terminal.

Essential Append to a log without wiping earlier lines

The default is overwrite. Pass -a when you are building a log file over multiple runs.

Run the command:

bash
PREFIX=tcs_
WORKDIR=/tmp/${PREFIX}lab
mkdir -p "$WORKDIR" && cd "$WORKDIR"
echo 'first line' | tee ${PREFIX}log.txt
echo 'second line' | tee -a ${PREFIX}log.txt
cat ${PREFIX}log.txt

Sample output:

text
first line
second line

After cat:

text
first line
second line

Each append adds to the end; tee still prints the new line to the terminal once per run.

Essential Write a root-owned file from a normal user pipeline

Shell redirection runs in your shell, so echo text > /etc/example fails without root. Put sudo on tee instead.

Run the command:

bash
PREFIX=tcs_
echo "root line" | sudo tee /tmp/${PREFIX}rootfile.txt
sudo cat /tmp/${PREFIX}rootfile.txt

Sample output:

text
root line
root line

The same pattern works for files under /etc when you need to capture installer or diagnostic output with elevated privileges.

Common Branch a pipeline — file plus another filter

tee can sit in the middle of a pipe: one copy goes to disk, the rest of the stream continues to the next command.

Run the command:

bash
PREFIX=tcs_
WORKDIR=/tmp/${PREFIX}lab
mkdir -p "$WORKDIR" && cd "$WORKDIR"
echo -e 'alpha\nbeta\ngamma' | tee ${PREFIX}chain.txt | grep beta
cat ${PREFIX}chain.txt

Sample output:

text
beta
cat output:
alpha
beta
gamma

grep only sees beta, but ${PREFIX}chain.txt keeps the full stream.

Common Save output to a file but hide it from the terminal

Send tee's stdout to /dev/null when you only care about the file copy.

Run the command:

bash
PREFIX=tcs_
WORKDIR=/tmp/${PREFIX}lab
mkdir -p "$WORKDIR" && cd "$WORKDIR"
echo 'hidden' | tee ${PREFIX}hidden.txt > /dev/null
cat ${PREFIX}hidden.txt

Sample output:

text
hidden

Nothing prints to the terminal, but the file still contains hidden.

Common Write one stream to multiple files

List more than one path and tee duplicates the input to each file and to stdout.

Run the command:

bash
PREFIX=tcs_
WORKDIR=/tmp/${PREFIX}lab
mkdir -p "$WORKDIR" && cd "$WORKDIR"
echo 'multi' | tee ${PREFIX}a.txt ${PREFIX}b.txt
md5sum ${PREFIX}a.txt ${PREFIX}b.txt

Sample output:

text
multi
a8f5f167f44f4964e6c998dee827110  /tmp/tcs_lab/tcs_a.txt
a8f5f167f44f4964e6c998dee827110  /tmp/tcs_lab/tcs_b.txt

Matching checksums confirm both files received the same bytes.

Advanced Control behavior when a write to disk fails

On full disks or read-only mounts, tee may fail while writing to a file even though stdout still works. --output-error chooses whether to warn or exit.

Run the command:

bash
PREFIX=tcs_
WORKDIR=/tmp/${PREFIX}lab
mkdir -p "$WORKDIR" && cd "$WORKDIR"
echo 'warn test' | tee --output-error=warn ${PREFIX}warn.txt

Sample output:

text
warn test

On GNU coreutils builds, pair -p with the default warn-nopipe mode when diagnosing permission or disk errors on regular files.

Advanced Write to a file whose name is a single dash

A bare - operand means a file named - in the current directory, not stdout.

Run the command:

bash
PREFIX=tcs_
WORKDIR=/tmp/${PREFIX}lab
mkdir -p "$WORKDIR" && cd "$WORKDIR"
echo 'dash test' | tee ./-
ls -la ./-

Sample output:

text
dash test
-rw-r--r-- 1 root root 10 Jul  1 14:18 ./-

Use ./- so the shell does not treat - as a special operand.


tee — when to use / when not

Use tee when Use something else when
  • You are in a pipeline and want output on the terminal and in a file
  • You need to append from a pipe without a subshell (tee -a)
  • You must write a root-owned path from a user pipeline (sudo tee)
  • You want to split a stream to a file and another command downstream
  • You are logging installer or test output while watching it live
  • You only need a file, not terminal output → shell redirection (>, >>)
  • You are not in a pipeline and only concatenating files → [cat](/cat-command-examples/)
  • You need to overwrite a file in place from a stream without a temp file → sponge from moreutils (not in coreutils)
  • You are filtering text and do not need a saved copy → grep alone

tee vs shell redirection

tee > / >>
Needs a pipeline Yes — reads stdin No — shell opens the file
Shows output on terminal Yes (unless you redirect stdout away) No
Append tee -a file >> file
Write protected paths as user sudo tee file sudo sh -c 'echo x > file' or editor
Split stream to file and another command Natural fit Requires process substitution or temp files

Use tee when the data is already flowing through a pipe. Use > or >> when you only need a file and do not care about terminal output.


Commands that often appear in the same pipelines and logging workflows.

Command One line
tee Copy stdin to files and stdout (this page)
sudo Elevate tee to write protected paths
wget Download to a file (no stdin copy needed)

Browse the full index in our Linux commands reference.


tee — interview corner

What does the tee command do in Linux?

tee reads standard input and writes that data to every file you name, while also copying it to standard output. The name comes from a T-splitter in plumbing — one stream becomes many outputs.

Typical pattern:

bash
dmesg | tee /tmp/boot.log

You see kernel messages on the terminal and save the same text to /tmp/boot.log. It is a coreutils utility and appears in almost every Linux distribution.

A strong answer is:

"tee copies stdin to one or more files and also to stdout. I use it in pipelines when I want to log output and still watch it, or when I need sudo tee to write a root-owned file from a normal user's pipe."

When would you use tee instead of > or >>?

Shell redirection (>, >>) connects a command's stdout directly to a file. The bytes never hit the terminal unless you use another tool.

tee fits when:

  • Output is already in a pipe (cmd1 | tee log | cmd2)
  • You want both a file and the terminal
  • You need sudo tee because redirection runs in your shell without elevated rights

Redirection fits when you only need the file and want the simplest syntax.

A strong answer is:

"I use tee inside pipelines when I need a file copy and visible output, or sudo tee for protected paths. Plain redirection is better when I only need the file and I'm not splitting a pipe."

Why is sudo tee common for editing /etc files?

When you run echo 'config' > /etc/foo.conf, your shell opens /etc/foo.conf for writing. The shell runs as your user, so the redirect fails on root-owned files.

sudo tee runs the write with root privileges while your upstream command stays unprivileged:

bash
echo 'config' | sudo tee /etc/foo.conf

Some admins add sudo tee -a to append to logs under /var/log the same way.

A strong answer is:

"Redirection is done by the shell as my user, so > /etc/file fails. sudo tee runs the write elevated while the generating command can stay unprivileged — that's the usual pattern for quick /etc updates from a pipe."

How do you append with tee without overwriting the file?

Pass -a or --append. Default tee truncates each output file before writing.

bash
./run-tests.sh | tee -a results.log

Each run adds to the end of results.log. This mirrors >> but works in the middle of a pipeline.

A strong answer is:

"tee -a appends to files instead of truncating them. I use it for build or test logs when each run should add lines without wiping earlier output."

Can tee sit in the middle of a pipeline?

Yes. tee writes its stdin to files, then passes the same data to stdout for the next stage.

bash
journalctl -u nginx --since today | tee /tmp/nginx.log | grep error

/tmp/nginx.log gets the full journal slice; grep only sees what tee forwards. That is the main reason tee exists — branching a live stream.

A strong answer is:

"Yes — tee duplicates the stream to disk and stdout, so I can log everything and still pipe a subset to grep or awk. The file gets the full stream; downstream tools get the same bytes tee prints."


Troubleshooting

Symptom Likely cause Fix
Permission denied writing the file File or directory not writable by your user sudo tee path or fix ownership/mode
Empty file but command printed output Wrong order — tee not in the pipe path Put tee where stdin carries the data: cmd | tee file
File truncated when you meant to append Missing -a Use tee -a file
Nothing on terminal but file is correct Stdout redirected away Remove > /dev/null on tee's stdout if you want to see output
tee: 'file': Is a directory Operand is a directory Pass a file path, not a directory
Interrupt still stops the pipeline -i not supported or signal hits upstream command Check tee --help on your build; protect the upstream command separately

Rohan Timalsina

is a technical writer and Linux enthusiast who writes practical guides on Linux commands and system administration. He focuses on simplifying complex topics through clear explanations.