From the tee
manual on my system:
The tee utility copies standard input to standard output, making a copy
in zero or more files. The output is unbuffered.
So, it reads from standard input and copies it to standard output, and while doing so also duplicates the stream into one or several files.
In the following pipeline, tee
would take the output of the first command in the pipeline and copy it to standard output (the terminal) while also making copies of it in the files one
, two
and three
:
$ somecommand | tee one two three
tee
has many uses, one is in conjunction with sudo
to redirect output to a file owned by root:
$ somecommand | sudo tee /root/somefile >/dev/null
The following would not have worked since the redirection happens as the unprivileged user (it would also run somecommand
as root which may be unwanted):
$ sudo somecommand >/root/somefile
An artificial example of appending a fixed set of lines to many files at once (to all users ~/.profile
files, assuming that the *
expands to the usernames and that the expanded command line does not become too long for the shell to handle):
$ tee -a /home/*/.profile <<'END_NEWPATH'
PATH="$PATH:/opt/bin"
END_NEWPATH
A real example of using tee
:
time doas box-build.sh 2>&1 | tee build.out | grep '^=*>'
This is me building the OpenBSD base system. doas
is the OpenBSD "equivalent" of sudo
and box-build.sh
is a small shell script that does the building (essentially cd /usr/src && make obj && make build
). I'd like to store the output of the whole build process, including any errors or warnings, but I don't want to have everything spewing out into my terminal. To this end I use tee
to save everything into build.out
and then grep
to only get a hint of where in the process we are in the terminal.
See also the other questions here that are tagged with the tee tag.
cat file
" will contain the contents of the filefile
, but it's still the standard output ofcat
, not of the file. – Kusalananda Apr 29 '17 at 11:45cat
just copies stuff as-is,wc -l
counts the lines in the input and prints that into its output,ls
takes no input from stdin, but asks the OS for a file listing, and then prints that to its standard output. – ilkkachu Apr 29 '17 at 12:03