30

Suppose I have a binary called foo.

If I want to redirect the output of foo to some other process bar, I could write ./foo | bar.

On the other hand, if I wanted to time foo, and redirect the output of time I could write, time (./foo) | bar.

My question is, how can I stick the output of time to the end of the output of foo and pipe it through the same pipe?

The following solution is not what I am looking for, because it starts two separate instances of the process bar, while I want a single shared pipe, to a single instance of bar.

time (./foo | bar)  | bar

For anyone who is curious, the reason for not wanting to start two instances of bar is because bar can be a network client and I want the timing information to be sent to the server as part of the same http POST message as the process output.

1

3 Answers 3

39

If I understand what you're asking for I this will do. I'm using the commands ls ~ and tee as stand-ins for ./foo and bar, but the general form of what you want is this:

$ ( time ./foo ) |& bar

NOTE: The output of time is already being attached at the end of any output from ./foo, it's just being done so on STDERR. To redirect it through the pipe you need to combine STDERR with STDOUT. You can use either |& or 2>&1 to do so.

$ ( time ./foo ) |& bar

-or-

$ ( time ./foo ) 2>&1 | bar

Example

$ ( time ls . ) |&  tee cmd.log
cmd.log
file1
file2
file3
file4
file5

real    0m0.005s
user    0m0.000s
sys     0m0.001s

And here's the contents of the file cmd.log produced by tee.

$ more cmd.log 
cmd.log
file1
file2
file3
file4
file5

real    0m0.005s
user    0m0.000s
sys     0m0.001s
4
  • Note that this syntax doesn't work for BASH.
    – jvriesem
    May 30, 2018 at 18:50
  • 1
    @jvriesem all the examples are from bash
    – slm
    May 30, 2018 at 22:55
  • The |& operator is not recognized at least as of v3.2.57. The knowledge I gained from this is the parentheses were necessary and create a subshell.
    – Govind Rai
    Feb 14, 2020 at 18:21
  • |& shows up in Bash 4. Control operators is covered here BTW - unix.stackexchange.com/questions/159513/….
    – slm
    Feb 14, 2020 at 22:44
12

time sends its output to stderr instead of stdout by default. You just need to redirect that where you want it.

You say "On the other hand, if I wanted to time foo, and redirect the output of time I could write, time (./foo) | bar." but this is actually incorrect. In this case, the output of time would still be displayed on your console, only stdout would be redirected.

You can redirect stderr specifically with:

(time foo) 2>&1 | bar

or all pipes with:

(time foo) |& bar

The brackets are needed for this to work correctly.

1
  • Thanks! Your answer helped me figure it out. The accepted answer mentions dollar sign in the beginning, I thought that's supposed to be part of the command and was confused why it wasn't working. Apr 27, 2023 at 7:37
0

I found that this works on Solaris. (time ls) &> file

1
  • 1
    This is no different to either of the existing solutions Jan 23, 2016 at 19:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .