tee can redirect the piped standard input into the standard output and file.

echo Hello, World! | tee greeting.txt

The command above would display the greeting on the terminal screen and save it in the contents of greeting.txt file, creating the file if there's none by that name.

There's also -a switch for tee to append to the existing file instead of overwriting.

Is there a convenient way to redirect the piped input to the command and standard output instead of file?

I am trying to create a wrapper script for buku to copy to primary selection the URL of the bookmark specified by its index number.

# bukuc:
url=$(buku -f 1 -p $1 | cut -f 2) # NUMBER : URL
echo $url # DISPLAY
echo $url | xsel # PRIMARY SELECTION

Here I use echo two times, first for displaying on the terminal, and then saving in the primary selection (clipboard).

I imagine something of echo $url | teeC xsel or a shortcut to display the output before passing to the next command (chaining commands), what would allow me to chain the whole command in one line without the need to save the result in a variable as follows:

buku -f 1 -p $1 | cut -f 2 | teeC xsel    

I can also use it with urlview to view, select, and open with the $BROWSER as follows:

bukuc 10-20 | urlview
  • 3
    Try tee /dev/tty or tty0 (dont remember exactly ... i am on the road) Jun 17 '17 at 19:08
  • 2
    info tee mentions process substitution, and pipe tee's output to a program...
    – Xen2050
    Jun 18 '17 at 10:34

It's straightforward in shells that support process substitution, e.g. bash

$ echo foo | tee >(xsel)
$ xsel -o

Otherwise, you could use a FIFO (although it lacks convenience)

$ mkfifo _myfifo
$ xsel < _myfifo &
$ echo bar | tee _myfifo
$ xsel -o
[1] + Done                       xsel 0<_myfifo
  • Thanks! Two things I noted: 1. sh (Bourne shell) doesn't support that feature; 2. The arrow has to stick as a part of the single operator >() for process substitution.
    – user86041
    Jun 17 '17 at 19:45

The direct analogue of "tee for commands" is the pee command from moreutils (tee, but with pipes). Its arguments are used as commands to run, not as paths, and they get the input piped to them rather than written to file. All of the commands are given the standard input you piped to pee as their own.

Using pee, you can get the result you wanted by telling it to run both xsel and cat with the input.

echo foo | pee xsel cat

There is an extra cat process floating around there to do the output, which isn't really a problem for your use case but could be less ideal other times. This works with any shell, unlike process substitution, but of course it does require an extra (probably less-common) tool installed.

You can give more complex commands by quoting them: pee "xsel --display :1" cat. They're run with sh, so you do have to be careful about shell metacharacters.

  • 5
    Very cool - didn't know about that Jun 18 '17 at 2:53
  • 5
    That's... not a good name. Jun 18 '17 at 11:29
  • As of today, it is available as a tarball, packaged for apt as a Debian package, so ... available to Ubuntu users in particular, but not available in AUR to pacman users. Last commit to the Github repo github.com/stigtsp/moreutils is 2 years old.
    – Cbhihe
    Apr 25 '20 at 10:35

Your Answer

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