Reputation: 8357
There seem to be two bash idioms for redirecting STDOUT and STDERR to a file:
fooscript &> foo
... and ...
fooscript > foo 2>&1
What's the difference? It seems to me that the first one is just a shortcut for the second one, but my coworker contends that the second one will produce no output even if there's an error with the initial redirect, whereas the first one will spit redirect errors to STDOUT.
EDIT: Okay... it seems like people are not understanding what I am asking, so I will try to clarify:
Can anyone give me an example where the two specific lines lines written above will yield different behavior?
Upvotes: 10
Views: 2629
Reputation: 1
I know its a pretty old posting..but sharing what could answer the question : * ..will yield different behavior?
Scenario: When you are trying to use "tee" and want to preserve the exit code using process substitution in bash... someScript.sh 2>&1 >( tee "toALog") # this fails to capture the out put to log
where as :
someScript.sh >& >( tee "toALog") # works fine!
Upvotes: 0
Reputation: 44118
The situation where the two lines have different behavior is when your script is not running in bash but some simpler shell in the sh family, e.g. dash (which I believe is used as /bin/sh in some Linux distros because it is more lightweight than bash). In that case,
fooscript &> foo
is interpreted as two commands: the first one runs fooscript in the background, and the second one truncates the file foo. The command
fooscript > foo 2>&1
runs fooscript in the foreground and redirects its output and standard error to the file foo. In bash I think the lines will always do the same thing.
Upvotes: 6
Reputation: 47286
From the bash manual:
There are two formats for redirecting standard output and standard error:
&>word
and
>&word
Of the two forms, the first is preferred. This is semantically equivalent to
>word 2>&1
The phrase "semantically equivalent" should settle the issue with your coworker.
Upvotes: 8
Reputation: 8916
The main reason to use 2>&1
, in my experience, is when you want to append all output to a file rather than overwrite the file. With &>
syntax, you can't append. So with 2>&1
, you can write something like program >> alloutput.log 2>&1
and get stdout and stderr output appended to the log file.
Upvotes: 3
Reputation: 204678
&>foo
is less typing than >foo 2>&1
, and less error-prone (you can't get it in the wrong order), but achieves the same result.
2>&1
is confusing, because you need to put it after the 1>
redirect, unless stdout is being redirected to a |
pipe, in which case it goes before...
$ some-command 2>&1 >foo # does the unexpected $ some-command >foo 2>&1 # does the same as $ some-command &>foo # this and $ some-command >&foo # compatible with other shells, but trouble if the filename is numeric $ some-command 2>&1 | less # but the redirect goes *before* the pipe here...
Upvotes: 2
Reputation: 4373
2>&1 depends on the order in which it is specified on the command line. Where &> sends both stdout and stderr to wherever, 2>&1 sends stderr to where stdout is currently going at that point in the command line. Thus:
command > file 2>&1
is different than:
command 2>&1 > file
where the former is redirecting both stdout and stderr to file, the latter redirects stderr to where stdout is going before it is redirected to the file (in this case, probably the terminal.) This is useful if you wanted to do something like:
command 2>&1 > file | less
Where you want to use less to page through the output of stderr and store the output of stdout to a file.
Upvotes: 1
Reputation: 139921
2>&1
might be useful for cases where you aren't redirecting stdout to somewhere else, but rather you just want stderr to be sent to the same place (such as the console) as stdout (perhaps if the command you are running is already sending stderr somewhere else other than the console).
Upvotes: 0
Reputation: 4872
&> foo # Will take all and redirect all output to foo.
2>&1 # will redirect stderr to stdout.
Upvotes: 1