On this page
tee
tee reads standard input and writes it, unchanged, to standard output and to each file you name. It is the T-junction of a pipeline: the data keeps flowing down the pipe while a copy is also captured on disk.
tee [options] [file...]
$ echo saved | tee note.txt
saved
$ cat note.txt
saved
The name is the shape of the letter T — one stream in, the same stream out two ways. That makes tee the tool for the moment you want to both see (or keep piping) some data and keep it at the same time.
Writing to several places at once
Every byte that arrives on standard input is written to standard output and to each named file. Name more than one file and each one receives a full, identical copy:
$ producer | tee a.log b.log c.log | consumer
Here producer's output reaches consumer down the pipe exactly as if tee were not there, and a.log, b.log, and c.log each end up holding the same complete copy of it. With no files named, tee copies input straight to standard output and nothing else — a plain pass-through.
tee does not buffer between reads: it writes each chunk out as it is read, so a file being written by tee fills up as the data flows, rather than all at once when the input ends.
Overwrite or append
By default, each named file is truncated — opened fresh, so any existing contents are discarded before the new data is written. A file that does not exist is created.
With -a (--append), tee appends to each named file instead: existing contents are kept and the new data is added to the end. A file that does not exist is still created.
$ echo first | tee log.txt # log.txt now holds "first"
$ echo second | tee -a log.txt # log.txt now holds "first" then "second"
Creating a file inherits a security descriptor
When tee creates a new output file — a named file that did not already exist — that file needs a security descriptor, and it inherits one from the directory it is created in. This is the same creation-inherits-a-descriptor rule that governs every file-creating tool on Peios; see Files and directories for the shared model.
With -a, when the named file already exists, tee opens that existing file to append and creates nothing, so no new descriptor is involved. Whether opening a file to write succeeds — whether creating a new one or writing an existing one — is decided by the normal access check against the relevant directory or file. tee reports a file it cannot open and, by default, carries on with the outputs it can write.
Files named -
tee gives no special meaning to -. A file argument of - refers to a file literally named - in the current directory; it is opened, created, and written exactly like any other named file. It is not a stand-in for standard output — standard output is always written and needs no naming.
Ignoring interrupts
With -i (--ignore-interrupts), tee ignores the interrupt signal (the one a terminal sends on Ctrl-C). This lets tee keep copying to its files even as an interrupt tears down the rest of a pipeline, so the capture is not cut short.
Behaviour on write errors
By default, if a write to one output fails, tee reports it and stops writing to that output, but keeps writing to the others; a broken-pipe error on standard output is treated quietly. Two options change this policy.
-p sets write-error behaviour so that errors on a pipe (a downstream reader that has gone away) are ignored while other write errors are still reported.
--output-error[=MODE] sets the policy explicitly. Given on its own, with no =MODE, it selects warn-nopipe. The modes are:
| Mode | Behaviour |
|---|---|
warn |
Warn on a write error to any output, including a broken pipe, and continue with the remaining outputs. |
warn-nopipe |
Warn on a write error that is not a pipe error, and continue. Broken-pipe errors are ignored. This is the mode selected by a bare --output-error. |
exit |
Exit on a write error to any output, including a broken pipe. |
exit-nopipe |
Exit on a write error that is not a pipe error. Broken-pipe errors are ignored. |
Options
| Option | Effect |
|---|---|
-a, --append |
Append to each named file rather than truncating it. |
-i, --ignore-interrupts |
Ignore the interrupt signal. |
-p |
Ignore errors from writing to a broken pipe, still reporting other write errors. |
--output-error[=MODE] |
Set the write-error policy: warn, warn-nopipe, exit, or exit-nopipe. A bare --output-error means warn-nopipe. |
Exit status
| Code | Meaning |
|---|---|
0 |
The input was copied to standard output and every named file without error. |
1 |
A file could not be opened, a write failed under a policy that reports or exits on it, or the input could not be read. |