VMware ESXi and vSphere Cluster Management

Split Program Output with the tee Command in Linux

Learn how Linux tee copies command output to the terminal and one or more files, including append mode, stderr capture, sudo, and pipeline errors.

The Linux tee command lets you watch command output in the terminal while saving the same data to one or more files. It is especially useful for diagnostic logs, reports, installation transcripts, and command results that you want to review later.

What the tee Command Does

tee reads data from standard input and copies it to two destinations:

  • Standard output: usually the terminal, so you can see the data live.
  • One or more files: so the data is retained.

Because it reads from standard input, tee is commonly placed after another command in a pipeline. A pipeline is a sequence of commands connected with the pipe operator, |.

Standard Streams and Pipelines

Linux commands normally use three standard streams:

StreamNameTypical purpose
0Standard input (stdin)Data a command reads, often from the keyboard or another command
1Standard output (stdout)Normal results produced by a command
2Standard error (stderr)Diagnostic messages and errors

For example, in this pipeline, ls sends its standard output into tee as standard input:

ls -l | tee output.txt

The pipe passes standard output from the command on its left to standard input for the command on its right. Ordinary use of tee captures standard output only. Standard error remains a separate stream unless you explicitly redirect it into the pipeline.

Basic tee Syntax

command | tee file
  • command is the producing command.
  • | sends that command's standard output into tee.
  • tee copies its standard input to standard output and to the named file.
  • file is the destination path.

Since tee writes a copy to standard output, the command's output continues to appear in the terminal.

Save a Directory Listing

Use the following command to display a detailed directory listing and save the same listing in output.txt:

ls -l | tee output.txt

If output.txt does not exist, tee creates it. If it already exists, the default behavior is to truncate it—that is, reduce it to zero length—and write the new output. Existing contents are therefore replaced.

Append Output with -a

Use the -a option to append incoming data after the existing end of a file:

ls -l | tee -a output.txt

Append mode preserves the old contents and adds the new listing. This is useful when collecting successive command results in one report:

date | tee -a system-report.txt
uname -a | tee -a system-report.txt
df -h | tee -a system-report.txt

Without -a, each command would replace the report. Choose overwrite or append deliberately.

Write to Multiple Files

tee accepts more than one filename. The same input stream is displayed in the terminal and written to every specified file:

command | tee first.txt second.txt

To append to both files instead, use:

command | tee -a first.txt second.txt

All named files receive identical input. If one destination cannot be opened or written, tee reports the problem; check its output and exit status when reliability matters.

Capture Standard Error

Error messages may appear on screen but be absent from the file because they use standard error rather than standard output. For example, this command can produce both a valid listing and an error:

ls existing-file missing-file | tee command.log

The normal result is piped to tee, but the message about missing-file is normally sent directly to the terminal through standard error.

Merge standard error into standard output before the pipe:

ls existing-file missing-file 2>&1 | tee command.log

Here, 2>&1 redirects file descriptor 2, standard error, to file descriptor 1, standard output. Both streams then enter tee, so both are displayed and saved.

tee Options and Behaviors

Syntax or optionEffect on fileTerminal displayTypical use
tee fileCreates or overwrites fileDisplays the inputSave a fresh result
tee -a fileCreates file or appends to itDisplays the inputAdd log entries or successive reports
tee file1 file2Creates or overwrites both filesDisplays the inputDuplicate output into two destinations
tee -a file1 file2Appends to both filesDisplays the inputMaintain multiple growing logs

Hide tee's Terminal Copy

Sometimes you need tee to write a file but do not want its copied output displayed. Redirect tee's standard output to /dev/null:

command | tee output.txt > /dev/null

/dev/null is a special device that discards data written to it. This does not stop tee from writing output.txt; it only discards the copy that would otherwise reach the terminal.

Write to Protected Files with sudo tee

A common mistake is to expect sudo to grant permission to a shell redirection:

sudo printf '%s\n' 'value' > /etc/example.conf

The shell performs > /etc/example.conf before sudo runs printf. The shell is still running as your normal user, so opening the protected file can fail.

Instead, send the content through a pipeline and let elevated tee open the destination:

printf '%s\n' 'value' | sudo tee /etc/example.conf > /dev/null

In this example, printf creates the content, sudo tee writes the protected file, and the final redirection suppresses tee's terminal copy. Use sudo tee -a when appending is intended.

Output Stream Patterns

Command patternWhat is displayedWhat is savedNotes
command | tee output.txtStandard outputStandard outputStandard error stays separate
command 2>&1 | tee output.txtStandard output and standard errorBoth streamsUseful for diagnostic logs
command | tee output.txt > /dev/nullNothing from teeStandard outputTerminal display is intentionally suppressed
command | sudo tee protected-file > /dev/nullNothing from teeStandard output in the protected fileUse when elevated write permission is required

Exit Status in Pipelines

A shell commonly reports the exit status of the last command in a pipeline. In:

command | tee output.txt

the reported status may be tee's status. If the first command fails but tee successfully receives end-of-file and writes the file, the overall pipeline can appear successful.

In shells that support it, enable pipefail:

set -o pipefail

With pipefail, the pipeline reports failure when a command in the pipeline fails, rather than hiding every earlier failure behind a successful final command.

In Bash, PIPESTATUS contains the individual statuses from the most recently executed pipeline. Inspect it immediately because another command can replace its contents:

command | tee output.txt
echo "${PIPESTATUS[@]}"

The values are listed in pipeline order: the first value belongs to command, and the second belongs to tee.

Safe File Handling

  • Use tee -a when preserving existing content is required.
  • Use plain tee file only when replacing the destination is intentional.
  • Inspect the destination path before running the command, especially when using absolute paths or sudo.
  • Check that the directory exists and that you have suitable write permissions.
  • Remember that overwrite mode does not preserve a prior version of the file.
  • Large output can consume substantial disk space, and a full disk or write error can prevent a complete log.

Troubleshooting tee

The destination file was replaced unexpectedly

Plain tee overwrites existing files by default. Use tee -a to add output without replacing the old content.

Errors appear on screen but are missing from the file

Only standard output was probably piped into tee. Merge standard error before the pipe:

command 2>&1 | tee command.log

sudo does not fix a protected-file error

The shell likely attempted redirection before sudo ran the producing command. Pipe the content into sudo tee instead:

command | sudo tee /path/to/protected-file

The output no longer appears in the terminal

Look for a final redirection such as > /dev/null. Remove it when you need the live terminal copy.

tee reports permission denied

The current user cannot create or modify the destination or its directory. Choose a writable path, correct ownership or permissions when appropriate, or use sudo tee only when privileged access is justified.

The first command failed but the pipeline looks successful

The shell may have reported tee's successful status. Enable set -o pipefail, or inspect Bash's PIPESTATUS immediately after the pipeline.

Practical Command Logging

For a live diagnostic transcript, merge both output streams and append to a report:

diagnostic-command 2>&1 | tee -a diagnostic.log

This keeps progress visible while preserving the transcript. For a new report, omit -a; for repeated runs where earlier results matter, keep -a and consider adding a timestamp before each section.

The central pattern is simple: command | tee file displays standard output and saves it at the same time. Add -a to preserve old file contents, add 2>&1 to capture errors, provide multiple filenames to duplicate the data, and use sudo tee when the destination itself requires elevated write permission.

See also: Split the output of a program.