31

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

41

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
    CommentedMay 30, 2018 at 18:50
  • 2
    @jvriesem all the examples are from bash
    – slm
    CommentedMay 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.CommentedFeb 14, 2020 at 18:21
  • |& shows up in Bash 4. Control operators is covered here BTW - unix.stackexchange.com/questions/159513/….
    – slm
    CommentedFeb 14, 2020 at 22:44
13

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.CommentedApr 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 solutionsCommentedJan 23, 2016 at 19:08

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.