What is the purpose of 'tee'?

What is the purpose of 'tee'?



All the usages of tee I ever saw were such:


tee


do_something | tee -a logfile



Or:


do_something_else | tee logfile



Is tee invented for those that don't know you can do the same with shell pipe redirections? Such as:


tee


do_something >> logfile



Or:


do_something_else > logfile



It's practically the same and it takes less keyboard hits to type out. What hidden features am I not seeing in tee?


tee






How was this not answered by the very first line of the man page "...and write to standard output and files"? The answers are interesting, but broadly talking about how pipes are useful just reinforces how this Q seems too broad, and should perhaps have been closed.

– Xen2050
Sep 12 '18 at 1:17






@Xen2050 A question cannot be blamed for a too-broad answer. The question is very specific, as is the current highest rated answer.

– Jon Bentley
Sep 14 '18 at 9:34






@JonBentley the question doesn't sound like "a specific problem with enough detail to identify an adequate answer" (as the close dialog reads). It does sound like this: "if your question could be answered by an entire book, or has many valid answers (but no way to determine which - if any - are correct), then it is probably too broad for our format." (Source: the Help Center)

– Xen2050
Sep 15 '18 at 8:02






@Xen2050 Are we reading the same question? It seems highly specific to me - what is the difference between tee and pipes? It has been adequately answered using two sentences. Far from an entire book. The fact that some answers choose to go off on a tangent has nothing to do with the scope of the question.

– Jon Bentley
Sep 15 '18 at 10:43






@JonBentley: Are we reading the same question?  R Moog kind-of sort-of implies a fairly well focused question — what is the difference between tee and I/O redirection?  The fact that it says “shell pipe redirections such as > and >>” is not a point in its favor, and is an argument for closing as unclear.  But it actually asks multiple questions: “What is the purpose of tee?”, “Is tee invented for those that don’t know you can do the same with shell pipe redirections?” and “What hidden features am I not seeing in tee?”.  At least two of those questions are too broad.

– G-Man
Sep 21 '18 at 2:32


tee


>


>>


tee


tee


tee




10 Answers
10



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.


do_something | tee -a logfile


logfile


do_something >> logfile



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


tee



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


sudo


cat


dd


buffer


tee






Multiple output is the key. tee can even take multiple arguments and write to many files at once.

– Kamil Maciorowski
Sep 10 '18 at 11:26


tee






I would call it a tee pipe fitting, not a crossing (as in a road intersection?) Stuff comes in one way and goes out both ways.

– user20574
Sep 11 '18 at 0:49






How would I use cat in a straightforward way instead of tee in e.g. echo /var/work/core.%p | sudo tee /proc/sys/kernel/core_pattern? echo /var/work/core.%p | sudo cat > /proc/sys/kernel/core_pattern doesn't work, because the redirect is processed by the non-sudo shell. As for dd, echo /var/work/core.%p | sudo dd of=/proc/sys/kernel/core_pattern works, but dd is often an overpowered tool capable of doing great damage, especially under sudo. As for buffer, its not installed by default in any of the RedHat- or Ubuntu-based distros I have to hand (or MacOS)...

– Digital Trauma
Sep 15 '18 at 2:58



cat


tee


echo /var/work/core.%p | sudo tee /proc/sys/kernel/core_pattern


echo /var/work/core.%p | sudo cat > /proc/sys/kernel/core_pattern


dd


echo /var/work/core.%p | sudo dd of=/proc/sys/kernel/core_pattern


dd


sudo


buffer






@EugenRieck I do get your point about about the 1:n relation between in:out being the primary function. However, neither the builtin cat nor /bin/cat work for me in this situation. It doesn't matter where cat comes from - the > will still be handled by the top level (non-sudo) shell. The advantage of tee over cat in this situation is that it allows the output file to be passed as a command-line param (and not a redirect). dd is certainly a viable option, though I'd still favour tee for this

– Digital Trauma
Sep 15 '18 at 16:15


cat


/bin/cat


cat


>


tee


cat


dd


tee






@EugenRieck What shell has cat and tee as builtins? And what version of sudo can run shell builtins?

– wjandrea
Sep 16 '18 at 4:07



cat


tee


sudo




Tee is not useless


Tee



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?


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).



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:


do_something


tee



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.


sudo


sudo


/dev/null



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



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:


tee






@Joe: sudo tee -a is probably a more recent innovation (I first saw it in Ubuntu guides / wikis especially for setting stuff in /proc/sys, because switching to Ubuntu was when I switched to a sudo based system (how Ubuntu is configured by default) instead of using su with a root password). I think tee predates sudo, so it's not a reason for tee existing. You don't need tee for that, it's simply shorter to type interactively than sudo sh -c 'cat > output'.

– Peter Cordes
Sep 11 '18 at 5:07



sudo tee -a


/proc/sys


sudo


su


tee


sudo


tee


tee


sudo sh -c 'cat > output'






With modern shells like bash, you can tee to feed two pipelines, like foo | tee >(pipe2) | pipe1. Or another fun one is ffmpeg ... |& tee /dev/tty | sed 's/.*r// > encode.log to see status-line updates interactively on the tty, while removing "lines" that end with carriage-return instead of newline for actual logging. (i.e. filter out the status-line updates). In general, you can stick a tee /dev/tty anywhere in a pipeline as a debug-print.

– Peter Cordes
Sep 11 '18 at 5:13



tee


foo | tee >(pipe2) | pipe1


ffmpeg ... |& tee /dev/tty | sed 's/.*r// > encode.log


tee /dev/tty






It's less a limitation of sudo you're working around and more a limitation of the shell's interpretation of >. When you run a command with sudo its stdout gets sent back to your shell program and further redirects with > are run with the shell's permissions. If you want to write with elevated permissions you need to have the elevated part of the pipeline be what does the writing. There are a large number of ways to do this depending on precisely what effect you're going for. If you really want to use > something like 'sudo bash -c "command > outfile" ' will do the job.

– Perkins
Sep 12 '18 at 18:14






Exactly, @Perkins. The shell parses the > and sets up the redirection before sudo even get exec'd, so it's definitely not a limitation of sudo that it doesn't handle things it never sees. :) I usually try to refer to this as "the sudo workflow" or some similar term when I'm explaining it, rather than describing sudo itself.

– dannysauer
Sep 13 '18 at 14:19


>


exec






sudo tee -a is IMHO an abuse of tee. Use sudo cat, sudo dd or (with best performance in many cases) sudo buffer if you don't need the multiple outputs.

– Eugen Rieck
Sep 14 '18 at 21:29


sudo tee -a


sudo cat


sudo dd


sudo buffer



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:


hi


stdout



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:


tee


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 is run as the user, while tee writes to the file as root):


echo


tee


root


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



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


tee


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


stdout


exec > >( tee output.log )






Not to forget exec > >(tee "$LOGFILE") 2>&1 in a bash script which lets the script output stdout and stderr to both, stdout and the file pointed to by $LOGFILE.

– rexkogitans
Sep 10 '18 at 13:45


exec > >(tee "$LOGFILE") 2>&1


$LOGFILE






@rexkogitans 2>&1 isn't that cmd batch syntax?

– dmb
Sep 10 '18 at 15:06






@dmb: It's shell syntax for "send stderr(=2) to the same place as stdout(=1)"

– psmears
Sep 10 '18 at 15:10






@rexkogitans It was a fair question really, I can't really know that you haven't used "Windoze" for a decade. I use 2>&1 to drop output and err to txt files in windows.

– dmb
Sep 10 '18 at 15:11


2>&1






@dmb I am sorry for sounding rude. It's all about psmears' comment. Obviously, Windows adopted Unix-style here.

– rexkogitans
Sep 10 '18 at 15:23




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.


tee


|



Example

Say for instance, you type ls /.

You'll get an output that looks something like:


ls /


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.


ls / > ls.txt



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


tee


|


ls / | tee ls.txt



Compare the two:


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






+1 for picture which as we know is worth a thousand words

– Sergiy Kolodyazhnyy
Sep 14 '18 at 4:57






If you had picked a garden hosepipe T piece, you would have been in line with Doug McIlroy's original metaphor.

– JdeBP
Sep 18 '18 at 16:21






@JdeBP Sorry, I have no idea who that is. Is he the original author of the utility or something? The flow of data & physical electrical current are often compared to hydraulic systems, but you probably know that. Anyway, I just chose this style to keep it super simple. I was actually going to do that to keep it familiar, but the garden variety tend to have more of a Y-shape and/or visually complicated attachments for attaching accessories, etc. It's essentially the same though.

– tjt263
Sep 19 '18 at 17:34






M. Douglas McIlroy, author of this famous memo who worked at Bell Labs and persuaded Ken Thompson to put pipes into Unix.

– JdeBP
Sep 20 '18 at 12:59



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.



tee is far from useless. I use it all the time and am glad it exists. It's a very useful tool if you have a pipeline that you want to split up. A very simple example is that you have some directory $d that you want to tar and you also want to hash it because you're paranoid (like I am) and don't trust the storage medium to hold the data reliably. You could write it to the disk first and then hash it, but that'd fail if the archive gets corrupted before it's hashed. Furthermore, you'd have to read it and if you work on files that are several hundred GB in size a lot, you will know that you really don't want to read them again if it doesn't have to be.


tee


$d



So what I do is simply this:


tar -c "$d" | tee >(sha256sum) >(cat > "$d"".tar") > /dev/null



It creates the tar ball and pipes it to tee which then pipes it to two sub-shells, in one of which it's hashed and in the other of which it's written to the disk.



It's also great if you want to perform several operations on a big file:


< file.tar.gz tee >(sha256sum) >(tar -xz) /other/storage/location/file.tar.gz > /dev/null



Reads the file once, hashes it (so you can check whether it's still as it should be), extracts it, and copies it to a different location. No need to read it three times for that.






Nitpick: tee does not create the subshells; the calling shell runs sha5sum and cat and connects their output to file descriptors which are passed to tee. Also, a useless use of cat; you can use input redirection to have tee read directly from file.tar.gz.

– chepner
Sep 10 '18 at 16:09


tee


sha5sum


cat


tee


cat


tee


file.tar.gz






@chepner You're right about the first interjection but you're completely wrong about the second one. I like writing my pipelines in order, so denoting the input at the right is terrible for readability and doing so is clearly objectively inferior to my method and totally not a subjective preference of mine. cat is love. cat is life.

– UTF-8
Sep 10 '18 at 16:59



cat


cat






You can also write < file.tar.gz tee >(sha256sum) ... if you are concerned about the lexical ordering of the redirections. That doesn't change the fact that there is no need for an entirely separate process just to feed a single file to tee.

– chepner
Sep 10 '18 at 17:13


< file.tar.gz tee >(sha256sum) ...


tee






@chepner Cool, thank you! Learned something today. :)

– UTF-8
Sep 10 '18 at 19:34






The cost of starting cat is relatively low. The cost of an extra 100 GiB of write + read system calls definitely wastes extra CPU time and memory bandwidth for your proposed example of a huge file. Remember that memory bandwidth is a shared resource across all cores, not to mention the extra pollution of L3 cache from that copying. On an x86 with Spectre + Meltdown mitigation enabled, system calls are more expensive than they used to be. You're using up a measurable amount of extra CPU time over the course of that copy. Also >(cat > foo) is not easier to understand than foo, IMO.

– Peter Cordes
Sep 11 '18 at 18:16


cat


>(cat > foo)


foo



Nitpick on @bertieb's answer that says 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.



There is no inherent limitation, only a misunderstanding of how the command is processed.



Example:



sudo echo 0 > /proc/sys/net/ipv4/ip_forward


sudo echo 0 > /proc/sys/net/ipv4/ip_forward



The current shell parses the command line. It finds the output redirection and performs that. Then it executes the command, which is the sudo and provides the remaining command line as arguments to the executed command. If the current shell does not have root permissions, then the output redirection will fail.


sudo



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


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



This works because the output redirection is deferred to the tee command, which at that point does have root permissions because it was executed via sudo.


tee


sudo



sudo bash -c "echo 0 > /proc/sys/net/ipv4/ip_forward"


sudo bash -c "echo 0 > /proc/sys/net/ipv4/ip_forward"



This works because the shell doing the redirection has root permissions.






Also, you might need sudo for the command, but not for the file being output and the redirection works just fine: sudo foo-needs-privilege > /tmp/this-output-file-doesnt

– Dennis Williamson
Sep 11 '18 at 0:37


sudo


sudo foo-needs-privilege > /tmp/this-output-file-doesnt



As other people have mentioned, piping output to the tee command writes that output to both a file and to stdout.


tee



I often use tee when I want to capture output from a command that takes a long time to run, while also wanting to visually inspect the output as the command makes it available. That way, I don't have to wait for the command to finish running before I inspect the output.


tee



What doesn't seem to have been mentioned yet (unless I missed it), is that the tee command can also write to multiple files at once. For example:


tee


ls *.png | tee a.txt b.txt



will write out all the *.png files in the current directory to two different files (a.txt and b.txt) at once.


*.png


a.txt


b.txt



In fact, you can type text to several different files at once with tee like this:


tee


$ tee --append a.txt b.txt c.txt d.txt
These lines are appended to four different files,
and are also written to stdout.
CTRL-D



The most common use of tee is to see the text on the terminal at the same time you send it to the file (or files). The wording of your question assumes you only ever write text to logfiles. I have scripts which write lists of filenames or directory names to trigger files (to be processed by other scripts asynchronously) and I use tee to send the same content to stdout. All stdout is directed to the logs. So I have my text where I want it and I have a log entry recording that I did this, all from a single 'echo' statement



tee is also the best method in Unix for making multiple identical files. I use it occasionally for making multiple empty files, like this ...


:|tee file01 file02 file03






why not touch? (more immediately obvious what is happening)

– Attie
Sep 10 '18 at 22:09



touch






@Attie touch will not truncate files if they already exist but only update their timestamps and leave their content as is; but tee will truncate them. Also, doing rm+touch is different than tee (think about hardlinks and symlinks)

– Matija Nalis
Sep 13 '18 at 23:29



touch


tee


rm


touch


tee






Then why not truncate -s 0? :-)

– Attie
Sep 14 '18 at 7:12


truncate -s 0



Imagine, you want to write the output of a command to a log file AND print to stdout. When you need to do it at the same time, then you need tee.


tee



A use case is to have build scripts that write the whole build to stdout (e.g. for Jenkins) but important stuff at the same time to a separate log file (for summary emails).



You'll really start missing tee when you have to script in Windows. There is no tee and that is really annoying.


tee


tee






Isn't it trivial to create?

– Lightness Races in Orbit
Sep 11 '18 at 17:50






It is not possible with batch/cmd as you can not split a stream of output from a command easily.

– domih
Sep 12 '18 at 8:53






Right but like a three-line C++ program...

– Lightness Races in Orbit
Sep 12 '18 at 8:59






The Windows unxutils distribution has many Unix command line tools which, unlike some distributions, do not pollute your Windows execution environment. The biggest limitation is on "glob"bing, which works differently on Unix/Linux than on Windows. "tee" is among the tools available.

– cmm
Sep 12 '18 at 13:18







Don't be silly, it's 2018. Use Powershell, it has tee. Cmd was never intended for serious scripting - that's what VBS was for. Powershell is the new go-to scripting tool. Granted, Cmd is still pretty powerful, but the command-line tools are pretty few.

– Luaan
Sep 13 '18 at 7:59



tee



Thanks for contributing an answer to Super User!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)