Looking at the two commands separately:
utility 2>&1 >output.log
Here, since redirections are processed in a left-to-right manner, the standard error stream would first be redirected to wherever the standard output stream goes (possibly to the console), and then the standard output stream would be redirected to a file. The standard error stream would not be redirected to that file.
The visible effect of this would be that you get what's produced on standard error on the screen and what's produced on standard output in the file.
utility 2>&1 | tee output.log
Here, you redirect standard error to the same place as the standard output stream. This means that both streams will be piped to the tee
utility as a single intermingled output stream, and that this standard output data will be saved to the given file by tee
. The data would additionally be reproduced by tee
in the console (this is what tee
does, it duplicates data streams).
Which ever one of these is used depends on what you'd like to achieve.
Note that you would not be able to reproduce the effect of the second pipeline with just >
(as in utility >output.log 2>&1
, which would save both standard output and error in the file by first redirecting standard output to the output.log
file and then redirecting standard error to where standard output is now going). You would need to use tee
to get the data in the console as well as in the output file.
Additional notes:
The visible effect of the first command,
utility 2>&1 >output.log
would be the same as
utility >output.log
I.e., the standard output goes to the file and standard error goes to the console.
If a further processing step was added to the end of each of the above commands, there would be a big difference though:
utility 2>&1 >output.log | more_stuff
utility >output.log | more_stuff
In the first pipeline, more_stuff
would get what's originally the standard error stream from utility
as its standard input data, while in the second pipeline, since it's only the resulting standard output stream that is ever sent across a pipe, the more_stuff
part of the pipeline would get nothing to read on its standard input.
Short answer: >
must be followed by a filename or &n
(n is a number), and |
must be followed by another command invocation.
Details: In shell syntax, a call to some command contains several components. Example:
A=foo 2>/dev/null B=bar cmd arg1 arg2 >file 3>&4 arg3
Here, parameters 2>/dev/null
, >file
and 3>&4
are special parameters (containing an unescaped >
¹), they are used to establish io-redirections, and can appear anywhere in the command line. Filedesciptor 2 is redirected to /dev/null
, filedescriptor 1
(implicit) is redirected to file
and filedescriptor 3
is redirected to what filedescriptor 4 was linked to.
Then, among remaining parameters, A=foo
and B=bar
contain =
, so they are not considered as the command name: they give specific values to environment variables of the process to be launched.
Then comes the command cmd
and the real arguments: arg1
, arg2
, arg3
.
The pipe |
is not part of a command invocation, it links two such invocations together. Example:
CC=gcc make 2>&1 | LESS=--quit-at-eof less
Output on filedescriptor 1 by the first process will be received as input on filedescriptor 0 by the second process, through a “pipe” which acts like a buffer.
—
1. In fact, the special characters like >
are sometimes seen followed by a space. Even though this is allowed, the two (space-separated) strings must be understood as a single ‘entity’.
Best Answer
In the first case,
cat
opens the file, and in the second case, the shell opens the file, passing it ascat
's standard input.Technically, they could have different effects. For instance, it would be possible to have a shell implementation that was more (or less) privileged than the
cat
program. For that scenario, one might fail to open the file, while the other could.That is not the usual scenario, but mentioned to point out that the shell and
cat
are not the same program.