Split Command Output to the Terminal and a File with tee in Linux
Learn how to use Linux tee to display command output in the terminal while saving it to one or more files, including append, errors, and sudo usage.
The Linux tee command duplicates data: it reads from standard input, sends a copy to standard output, and writes another copy to one or more files. This lets you watch a command while preserving its output for later review.
tee is a pipeline component, not a replacement for the command producing the output. The producing command still does the work; tee receives and duplicates its output.
Standard streams and pipelines
Linux commands commonly use three standard streams:
- Standard input (stdin) is the input a command reads. It commonly comes from the keyboard or from another command through a pipe.
- Standard output (stdout) is normal command output, usually displayed in the terminal.
- Standard error (stderr) is a separate stream for warnings, errors, and diagnostic messages.
A pipeline uses the pipe operator, |, to send the standard output of one command to the standard input of another command:
first-command | second-command
When you write command | tee file, the command's stdout becomes tee's stdin. By default, tee sends its stdout to the terminal, so the data remains visible while also being written to the file.
This is a form of redirection: shell syntax that changes where input or output is read from or written to. Unlike a simple > redirection, tee can preserve the terminal display.
Basic tee syntax
command | tee filename
commandproduces the data.|passes that command's stdout intotee.teedisplays the received data and writes it to the destination.filenameis the file that receives a copy.
For example, this displays a detailed directory listing and saves the same listing in output.txt:
ls -l | tee output.txt
The listing appears in the terminal and is written to output.txt. If that file already exists, its contents are replaced.
Overwrite versus append
By default, tee overwrites a destination file. Overwriting means replacing its existing contents with the new output.
Use -a, also written --append, to append output. Appending means adding data after the existing contents instead of replacing them.
date | tee -a output.txt
This prints the current date and adds it to the end of output.txt. Append mode is useful for repeated command runs, diagnostic logs, and reports that should retain earlier results.
| Option | Meaning | Typical use |
|---|---|---|
-a / --append | Add output to an existing file | Preserve earlier log or report entries |
--help | Display usage information | Review available options |
Writing to multiple files
tee accepts multiple file paths. Every specified file receives the same input, while the output is still displayed on screen.
printf '%s\n' 'report complete' | tee report.txt backup-report.txt
The message is printed in the terminal and stored in both report.txt and backup-report.txt. Without -a, each destination is overwritten. To append to several files, combine -a with the paths:
command | tee -a report.txt backup-report.txt
Capturing standard error
A basic pipeline sends stdout to tee, but stderr normally remains separate. As a result, an error can appear on the screen without being included in the saved file.
Use 2>&1 to merge stderr (file descriptor 2) into stdout (file descriptor 1) before the pipe:
find /etc -type f 2>&1 | tee find-results.log
This displays and records both discovered paths and access-related diagnostics. Because the streams are merged, normal output and error messages appear together in find-results.log; the file no longer separates them by stream.
| Goal | Shell pattern | What is saved |
|---|---|---|
| Display and overwrite a file | command | tee file | stdout, replacing the file |
| Display and append to a file | command | tee -a file | stdout, added after existing content |
| Record stdout and stderr | command 2>&1 | tee file | Both streams, merged together |
| Write to several files | command | tee file1 file2 | The same stdout in both files |
Using tee with protected destinations
Some paths, such as files under /etc, are owned by the system and cannot normally be written by an ordinary user. A common mistake is putting sudo before the producing command:
sudo printf '%s\n' 'example setting' > /etc/example.conf
Here, the shell performs > redirection before the command runs. The shell itself attempts to open the protected file, so sudo does not necessarily grant permission to the redirection.
Instead, run tee with elevated privileges. This gives the process that opens the destination file the required permission:
printf '%s\n' 'example setting' | sudo tee /etc/example.conf > /dev/null
tee still writes its input to standard output. Redirecting that output to /dev/null discards the duplicate terminal display, so the line is not printed a second time in contexts where you do not want it shown.
For a protected log where earlier entries must remain, use append mode:
command | sudo tee -a /protected/path/log.txt
Common use cases
- Reports: Save a directory listing, status check, or other command result while watching it.
- Installation and build records: Observe installation, compilation, or test output and retain a copy for troubleshooting.
- Diagnostic logs: Append repeated command results, often including a timestamp.
- Generated text: Send text from
printfor another pipeline into a file.
{ date; command; } 2>&1 | tee -a diagnostic.log
The grouped commands produce a timestamp and command output. The merged streams are displayed and appended to diagnostic.log.
Verifying and controlling tee output
Because tee passes its input to stdout, its output can continue through another pipeline component:
command | tee output.txt | less
In this example, the output is saved to output.txt, while less receives the same data for interactive viewing. If you want the output only in the file, discard tee's stdout:
command | tee output.txt > /dev/null
You can inspect a saved file afterward with a command such as cat output.txt or less output.txt.
Troubleshooting tee
The destination lost its previous contents
tee was probably used without append mode. Use tee -a filename when existing contents must be preserved.
Errors appear on screen but not in the file
Only stdout was piped into tee. Merge stderr before the pipe:
command 2>&1 | tee output.log
Writing to a system-owned file fails
The process running tee lacks write permission. When the write is intentional and the path has been confirmed, run tee through sudo:
command | sudo tee /protected/path
The output appears twice with sudo tee
This is expected: tee writes to the target file and to stdout. Redirect its stdout to /dev/null if terminal output is not wanted:
command | sudo tee /protected/path > /dev/null
The file is empty or lacks expected diagnostics
The source command may produce no output, or it may write diagnostics to stderr. Run the source command independently to check its behavior, then use 2>&1 when both streams should be captured.
Key points
teereads stdin and duplicates it to stdout and specified files.command | tee filedisplays stdout and overwritesfile.tee -a fileappends instead of overwriting.- Multiple file paths make identical copies in each destination.
- Use
2>&1before the pipe to record stderr together with stdout. - Use
sudo tee, not merelysudobefore the producing command, when tee must write a protected path.
For related command-line fundamentals, see Bourne Again Shell (Bash), searching for text with grep, and managing file ownership.