>& file
is a csh operator (from the late 70s) to redirect both stdout and stderr to file
. The Bourne shell (also from the late 70s) equivalent is > file 2>&1
, or 2> file >&1
, that is redirect fd 1 to file
and then fd 2 to the same open file description or vice versa.
zsh
and bash
are two shells (from the late 80s, early 90s) that took features from both the Korn¹ shell (and by extension the Bourne shell) and csh, and support that >&
csh operator in addition to the [i]>&j
Bourne/Korn operator.
Those two conflicts though.
cmd >& "$var"
Will end up doing the Bourne/Korn redirection if $var
contains a number and the csh one otherwise.
In practice, it's better to avoid that csh operator and use the Bourne syntax instead (cmd > "$var2" 2>&1
) in those shells to avoid surprises.
Note that initially, bash
didn't support csh's >&
but had &>
instead for the same feature. That also conflicted with Bourne syntax. In the Bourne shell, cmd &> file
is cmd
and > file
run in parallel. zsh
also added support for &>
latter for compatibility with bash
.
You'll find yet different syntax in different shells. In rc
(late 80s) and derivatives (es
, akanga
), Bourne's 2>&1
is written >[2=1]
(and it makes it easier to specify which fds are to be at each end of pipes: cmd1 |[3=4] cmd2
(connecting fd 3 of cmd1
to fd 4 of cmd2
via a pipe) which in Bourne syntax, you'd need to write { cmd1 3>&1 >&5 5>&- | 4<&0 <&6 6<&- cmd2; } 5>&1 6<&0
).
The fish
shell (mid 2000s) has different variations in I/O redirection syntax from the Bourne shell's.
¹ The Korn shell (from the early 80s) was based on the Bourne shell but also borrowed features from csh like aliases, tilde expansion and brace expansion.
2>&1
means justdup2(1, 2)
and is absolutely the same as2<&1
. After it, the2
and1
fds can be used interchangeably. Don't try to read to much into; the only difference between<&
and>&
is what fd is the default on the left side when not specified (0
vs1
).