How can I redirect `time` output and command output to the same pipe?

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

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.