tee Command in Linux with Examples

By 

•

Updated on

•

7 min read

tee command examples in Linux

When you run a command, you often want to see its output and save it to a file at the same time. A plain > redirect writes the output to a file, but nothing is shown on the screen.

The tee command reads from the standard input and writes to both standard output and one or more files at the same time. The name comes from the T-splitter used in plumbing. tee is mostly used in combination with other commands through piping. Our guide to Linux pipes explains how the | operator connects each stage.

This guide explains how to use tee to save and append output, capture error messages, and write to files that require root privileges.

tee Command Syntax

The syntax for the tee command is as follows:

txt
tee [OPTIONS] [FILE]...
  • OPTIONS :
    • -a (--append) - Do not overwrite the files; instead, append to the given files.
    • -i (--ignore-interrupts) - Ignore interrupt signals.
    • Use tee --help to view all available options.
  • FILE - One or more output files. Each file receives the input data.

How to Use the tee Command

The most basic usage of the tee command is to display the standard output (stdout) of a program and write it to a file.

In the following example, we are using the df command to get information about the amount of available disk space on the file system. The output is piped to the tee command, which displays the output to the terminal and writes the same information to the file disk_usage.txt.

Terminal
df -h | tee disk_usage.txt
output
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           1.1G  1.7M  1.1G   1% /run
/dev/vda1        29G  6.7G   22G  24% /
tmpfs           2.7G     0  2.7G   0% /dev/shm
efivarfs        256K  3.0K  253K   2% /sys/firmware/efi/efivars
tmpfs           2.7G   17M  2.7G   1% /tmp
none            1.0M     0  1.0M   0% /run/credentials/systemd-journald.service
none            1.0M     0  1.0M   0% /run/credentials/systemd-resolved.service
/dev/vda13      891M  111M  718M  14% /boot
/dev/vda15       98M  6.5M   91M   7% /boot/efi
none            1.0M     0  1.0M   0% /run/credentials/systemd-networkd.service
none            1.0M     0  1.0M   0% /run/credentials/serial-getty@ttyAMA0.service
tmpfs           539M   68K  539M   1% /run/user/1000

You can view the content of the disk_usage.txt file using the cat command .

Here is another simple example that saves kernel messages while still showing them on screen:

Terminal
sudo dmesg | tee /tmp/dmesg.log

On Ubuntu and other systems that restrict access to the kernel ring buffer, dmesg must be run with sudo. Only dmesg runs with elevated privileges. The tee command runs as your user and writes the file to /tmp.

Using tee in a Pipeline

The tee command passes its input through to the standard output. You can place it between two commands to save an intermediate result and keep the pipeline going.

The following command saves the list of files in /etc to etc-files.txt and passes the same list to the wc command to count the lines:

Terminal
ls /etc | tee etc-files.txt | wc -l
output
248

Only the line count is printed on the screen. The standard output of tee goes to wc, and the full list of files is saved in etc-files.txt.

Write to Multiple Files

The tee command can also write to multiple files. To do so, specify a list of files separated by space as arguments:

Terminal
command | tee file1.out file2.out file3.out

Append to File

By default, the tee command will overwrite the specified file. Use the -a (--append) option to append the output to the file :

Terminal
command | tee -a file.out

Without -a, tee empties the file as soon as it starts, even before the command produces any output.

Capturing Errors

The pipe passes only the standard output of a command to tee. Error messages are written to the standard error. They are shown on the screen but are not saved to the file.

To capture both streams, redirect the standard error to the standard output before the pipe:

Terminal
command 2>&1 | tee output.log

In the following example, ls lists one file that exists and one that does not:

Terminal
ls /etc/hostname /nonexistent 2>&1 | tee ls.log
output
ls: cannot access '/nonexistent': No such file or directory
/etc/hostname

Both lines are saved to ls.log. Without 2>&1, the file contains only /etc/hostname.

In Bash, you can use |& as a shorthand for 2>&1 |. For more information, see our guide on how to redirect stderr to stdout in Bash .

Ignore Interrupt

When you press Ctrl+C, the terminal sends the interrupt signal (SIGINT) to all commands in the pipeline, including tee. By default, tee exits immediately. Any output the first command prints after that is lost.

To ignore interrupts, use the -i (--ignore-interrupts) option. tee keeps reading until the command on the left exits, and the file receives the complete output.

A good example is ping . It prints a summary of the statistics after you press Ctrl+C:

Terminal
ping linuxize.com | tee -i ping.log

When you stop ping, the summary is shown on the screen and saved to ping.log. Without -i, the summary may be lost.

Hide the Output

If you do not want tee to write to the standard output, you can redirect it to /dev/null :

Terminal
command | tee file.out >/dev/null

For a quiet append, combine -a with the same redirect:

Terminal
command | tee -a file.out >/dev/null

Using tee with sudo

Suppose you want to write to a file that is owned by root as a sudo user. The following command will fail because the redirection of the output is not performed by sudo. The redirection is executed as the unprivileged user.

Terminal
sudo echo "newline" > /etc/file.conf

The output will look something like this:

output
bash: /etc/file.conf: Permission denied

Instead, prepend sudo before the tee command as shown below:

Terminal
echo "newline" | sudo tee -a /etc/file.conf

The echo command sends the text through the pipe, and sudo runs tee with permission to write to the protected file.

The -a option appends the line to the file. Without it, tee replaces the entire file content. This is rarely what you want with a system configuration file.

tee also prints the text on the screen. Installation guides often add > /dev/null to the end of the command to keep the terminal clean.

To write several lines at once, combine sudo tee with a heredoc :

sh
sudo tee /etc/myapp.conf > /dev/null <<'EOF'
[server]
port = 8080
EOF

Quoting the EOF delimiter prevents the shell from expanding variables and commands inside the block. The text is written to the file exactly as typed.

You can also use sudo tee from Vim. If you opened a root-owned file without sudo, type :w !sudo tee -- %:S to save it. The :S modifier escapes the filename for the shell, including spaces and special characters. After confirming that the write succeeded, reload the file with :e! to clear the modified state. For more ways to save and exit, see our guide on how to save a file in Vim .

Quick Reference

For a printable quick reference, see the tee cheatsheet .

TaskCommand
Write output to file and terminalcommand | tee file.txt
Append to a filecommand | tee -a file.txt
Write to multiple filescommand | tee file1.txt file2.txt
Write output and errors to a filecommand 2>&1 | tee file.txt
Keep writing after Ctrl+Ccommand | tee -i file.txt
Suppress terminal outputcommand | tee file.txt >/dev/null
Write to a root-owned fileecho "text" | sudo tee -a /etc/file.conf

Troubleshooting

The file is empty after sort file.txt | tee file.txt
tee truncates the output file as soon as it starts. This often happens before the first command has read the file. Do not write to the same file the pipeline reads from. Save the output to a different file instead.

Output appears all at once, not line by line
Many programs buffer their output when it goes to a pipe. tee receives the data in large blocks and prints them with a delay. For grep, use the --line-buffered option. For many other commands, run them through stdbuf -oL to switch the standard output to line buffering.

Conclusion

When collecting logs across several runs, use tee -a to keep earlier output. For other ways to send output to a file, see our guide on how to write to a file in Bash .

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 1000+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page