What is the purpose of 'tee'?

What you don't see is that do_something | tee -a logfile puts the output into logfile and to stdout, while do_something >> logfile puts it only into the logfile.

The purpose of tee is to produce a one input, multiple output scenario - just like in a 'T' crossing.

EDIT

There have been comments around how tee enables more seemless use of sudo. This is beside the point: cat, dd or maybe better buffer provide this possibility with better performance, if you don't need the multiple outputs. Use tee for what it is designed, not for what it "can also do"


Tee is not useless

Maybe you knew that anyway? If not, read on! Or if you know how it works, but aren't sure why it exists, skip to the end to see how it fit in the with the Unix philosophy.

What is the purpose of tee?

At its simplest, it takes data on standard input and writes that to standard output and one (or more) files. It has been likened to a plumbing tee piece in the way it splits one input into two outputs (and two directions).

Examples

Let's take your first example:

do_something | tee -a logfile

This takes the output of do_something and appends it to logfile, while also displaying it to the user. In fact, the Wikipedia page on tee has this as the second example:

To view and append the output from a command to an existing file:

  lint program.c | tee -a program.lint

This displays the standard output of the lint program.c command at the computer and at the same time appends a copy of it to the end of the program.lint file. If the program.lint file does not exist, it is created.

The very next example has another use: escalation of permissions:

To allow escalation of permissions:

cat ~/.ssh/id_rsa.pub | ssh admin@server "sudo tee -a /root/.ssh/authorized_keys2 > /dev/null"

This example shows tee being used to bypass an inherent limitation in the sudo command. sudo is unable to pipe the standard output to a file. By dumping its standard out stream into /dev/null, we also suppress the mirrored output in the console. The command above gives the current user root access to a server over ssh, by installing the user's public key to the server's key authorization list.

Or perhaps you want to take the output of one command, write that somewhere and also use that as input to another command?

You can also use tee command to store the output of a command to a file and redirect the same output as an input to another command.

The following command will take a backup of the crontab entries, and pass the crontab entries as an input to sed command which will do the substitution. After the substitution, it will be added as a new cron job.

$ crontab -l | tee crontab-backup.txt | sed 's/old/new/' | crontab –

(credit to Tee command usage examples)

Tee works with the Unix philosophy:

Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.

(Credit to Basics of the Unix Philosophy)

tee fits all of these:

  • it does one thing: creates an extra copy of input
  • it works with other programs because it is the glue (or a 'T' plumbing piece if you prefer) that lets other programs work together as in the examples above
  • it does this by manipulating a text stream given on standard input

It's practically the same and it takes less keyboard hits to type out.

It is not the same at all...

The following appear to be somewhat equivalent, but they're not:

$ echo "hi" > test.txt
$ echo "hi" | tee test.txt
hi

The critical difference is that the former has written the data only to the named file, while the latter has written hi to the terminal (stdout) and the named file, as shown below:

redirect vs tee


tee allows you to write the data to a file and use it in an onward pipeline, allowing you to do useful things - like keeping data from partway through a pipeline:

grep '^look ' interesting_file.txt \
  | tee interesting_lines.txt \
  | sort

Or, you can write to a file with elevated privileges, without giving the whole pipeline elevated privileges (here echo and the shell are running as the user, while tee writes to the file as root):

echo 0 \
  | sudo tee /proc/sys/net/ipv4/ip_forward

With tee, you can write to many files (and stdout):

echo "hi" \
  | tee a.txt b.txt

It's also possible to use exec with tee to record all of a script's output to a file, while still allowing an observer (stdout) to see the data:

exec > >( tee output.log )

This is a tee:
enter image description here

A T-shaped pipe fitting. It has an inlet, and two separate outlets.
In other words, it splits one pipe into two; like a fork in the road.

Similarly, tee is a pipe (|) that allows you to redirect your standard input to two separate outputs.


Example
Say for instance, you type ls /.
You'll get an output that looks something like:

Applications    Network     Users       bin        dev      net      private    tmp         var
Library         System      Volumes     cores      etc      home     opt        sbin        usr

Redirect the output to a text file, ls / > ls.txt, and no output is displayed in the shell, only in the resulting text file.

Want to see the output, AND pass it to a text file at the same time?
Add a tee to your pipe (|) ie: ls / | tee ls.txt


Compare the two:

ls /          >          ls.txt
ls /        | tee        ls.txt

No. You happen to mention one of the few examples where you could indeed redirect to the file using > and >> operators.

But Tee can do much more. Because you pipe to it, you can then pipe to something else.

A good example is listed on the wikipedia page:

find "4DOS" wikipedia.txt | tee 4DOS.txt | sort > 4DOSsorted.txt

Basically, you can pipe to Tee, so you can then pipe from Tee to something else. If all you want to do is write a log file, yes, then you don't really need Tee.