I know that to capture a pipeline's contents at an intermediate stage of processing, we use tee as ls /bin /usr/bin | sort | uniq | tee abc.txt | grep out , but what if i don't want to redirect the contents after uniq to abc.txt but to screen(through stdout, ofcourse) so that as an end result , i'll have on screen, the intermediate contents after uniq as well as the contents after grep.

  • 1
    The problem is stdout is a pipe to grep out. It's not your terminal anymore. Do you have any sort of guarantee that this will always be run from a terminal? – Joe Sewell Jan 12 '15 at 17:50
  • @JoeSewell In my case, yes from a terminal, but please tell what are the other sources from apart from terminal(are you talking about simply shell-scripting or something else). Just curious. I'm new to Linux and would love to explore what you are talking in detail. – Aman Jan 12 '15 at 17:53
  • One of my comments to an answer below gives a few examples. Running it from within gvim may leave you without a terminal at all. Having this line in a gmake makefile may cause problems if the -j option is used, and the subshell in use doesn't have access to the terminal. cron jobs wouldn't have a terminal, either. A shell script, on the other hand, might have a terminal, unless it's run without one. – Joe Sewell Jan 12 '15 at 17:58
  • @JoeSewell thanks, i'll do some research on them :) – Aman Jan 12 '15 at 18:18

sometimes /dev/tty can be used for that...

ls /bin /usr/bin | sort | uniq | tee /dev/tty | grep out | wc
  • 3
    This assumes the command is run from a terminal. – Joe Sewell Jan 12 '15 at 17:48
  • 1
    ls /bin /usr/bin | sort | uniq | tee /dev/tty | grep out | wc > out only contains the output from wc. – user7543 Feb 12 at 20:14
  • 1
    @user7543 tee -o out will give you tee output you can dan do wc >> out to append output to the file (depending on nonglobering settings that is). I would use file descriptor for both tee and grep and cat it. – Kamil Kurzynowski 2 days ago
ls /bin /usr/bin | sort | uniq | tee /dev/fd/2 | grep out | wc

On a linux system you can use the the /dev/fd/[num] links like named pipes in many cases. This will duplicate stdout to stderr, which, typically, is your terminal screen, but doesn't need to be.

  • Only works with bash, not dash /bin/sh on Ubuntu. I use this command for docker build: ID=$(docker build "$dockercontext" 2>&1 | tee /dev/fd/3 - | tail -1) – Daniel Alder Oct 15 '15 at 13:15
  • @DanielAlder - it works fine with dash. but you need to direct it somewhere. where does &3 go? the fd/2 above assumes the command is run from a terminal and &2 goes to the tty. for example: dash -c '{ echo hey; read v; echo "${v#?}" >/dev/fd/2; } <>/dev/fd/1 |:' – mikeserv Oct 16 '15 at 5:24
  • You are right. Didn't realize that /dev/fd/* are now also supported in dash. fd/3 is redirected to stdout in my case. I use this command line now, the other variant was overkill: ID=$(docker build "$1" 2>&1 | tee /dev/fd/2 - | tail -1) – Daniel Alder Oct 16 '15 at 7:51
  • @DanielAlder - those dont really have anything to do with the shell. theyre just files. or... links to file-descriptors anyway. but the shell doesnt put them there or control their behavior at all - those are handled by the kernel. the shell just does open() and dup2() with file-descriptors and it treats those exactly the same as it does any other file. – mikeserv Oct 16 '15 at 7:59
  • You don't know the history, and I didn't know the current situation. Not many years ago, there was no /dev/fd/ in the system. It was compiled directly in bash like /dev/tcp/ too which can be used to open tcp connections. Actually, bash still supports the emulation in case it can't find /dev/fd. Obviously I missed some developments of /proc/self, udev and the kernel so I didn't know that this is now system default. – Daniel Alder Oct 16 '15 at 8:30

This command worked for me.

ls /bin /usr/bin | sort | uniq | tee /dev/pts/0 | grep out

You could check what is your terminal using the command tty and replace the tee to redirect the output to that terminal.



  • That assumes the command runs on the terminal /dev/pts/0. – Joe Sewell Jan 12 '15 at 17:48
  • @JoeSewell, you could see which is the running terminal using tty. I have updated with that information. – Ramesh Jan 12 '15 at 17:49
  • Nice update, but why not use /dev/tty instead? That assumes, of course, that the command even has access to the terminal. If it's run from, for example, inside gvim, there may be no terminal involved at all. Doing this within gmake could become even more complex with multiple jobs, since not all processes can get to "the terminal." – Joe Sewell Jan 12 '15 at 17:53
  • Or use the output of the tty command? tee `tty` etc. – user7543 Feb 10 at 14:08
mkfifo myfifo
cat myfifo& ls /bin /usr/bin | sort | uniq | tee myfifo | grep out

mkfifo creates a FIFO (first in, first out) special file, a.k.a. a named pipe.  Start an asynchronous cat to read from the fifo, and then run your pipeline, teeing the intermediate result to the fifo.

This will produce a [1]+ Done cat myfifo message at the end.  You can suppress that with this magic trick:

(cat myfifo&); ls /bin /usr/bin | sort | uniq | tee myfifo | grep out

For a long term, robust solution, you might want to create a permanent fifo (e.g., $HOME/myfifo) rather than creating a new one every time.  But that will fail if you may be running multiple instances of this simultaneously.  Alternatively,

  • Generate a unique name (e.g., with mktemp).
  • Create the fifo in a directory that's guaranteed to be writable (e.g., /tmp).
  • Remove the fifo at the end of the command.

In the case this is being run from a terminal you could

  • start a terminal multiplexer such as tmux or screen
  • split your terminal - in tmux Ctrl B"
  • in the first window touch abc.txt then tail -f abc.txt
  • switch to the second window and run your command. You'll see the file created by tee update.

How to do it (example):

3>&1 ls |( tee >&3 ) >/dev/null

Which will show the ls result and send it to nirvanah.

To grok the key part, 3>&1, you may read I/O Redirection and esp. this example.

In short: >somefileis short for 1>somefile, which in turn means Assign the file handle of somefile to file descriptor 1 (and drop the former value of that descriptor, for the scope of this process).

So, 3>&1 means: Assign the file descriptor 1 (which may but need not be tty) to the (until now unused) file descriptor 3. We're effectively using &3 as a temporary variable.



cat stuff | 3>&1 tee 3 | xsel -i

Edit: unfortunately, the above ↑ is incorrect. An earlier answer of

cat stuff  | tee >(cat) | xsel -i

is good though.

  • (1) It seems to me that this does not do what the question asks for.  (2) TLDP is not a good source of information; please do not use it.  (3) I don’t see much correlation between the page you linked to and your answer.  Why are you giving TLDP credit (/ blame)?  (4) The question is about a pipeline involving ls, sort, uniq and grep.  It’s good manners to answer the question that was asked — and yet your answer shows a pipeline involving cat (a UUOC, BTW) and xsel. … (Cont’d) – Scott Mar 16 '20 at 3:15
  • (Cont’d) … (5) Please don’t clutter our site with answers that you know to be wrong, unless you have a good reason to do so.  Instead of adding a second answer (and, inexplicably, calling it an “earlier answer”), just delete the wrong answer and replace it with the one that’s less bad. – Scott Mar 16 '20 at 3:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.