# tee

_Peios / Using Peios / Peiosutils / Output and evaluation_

> Copy standard input to standard output and to each named file at once.

`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](/peios/security-fundamentals/security-descriptors/overview.md), 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](/peios/using-peios/peiosutils/files-and-directories/overview.md) 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. |

Related content:

- [echo](/peios/using-peios/peiosutils/output-and-evaluation/echo.md)
- [Output and evaluation](/peios/using-peios/peiosutils/output-and-evaluation/overview.md)
- [Files and directories](/peios/using-peios/peiosutils/files-and-directories/overview.md)
- [Security descriptors](/peios/security-fundamentals/security-descriptors/overview.md)
