1

From the bash man pages, under the section "Redirection":

Redirecting Standard Output and Standard Error

This construct allows both the standard output (file descriptor 1) and the standard error output (file descriptor 2) to be redirected to the file whose name is the expansion of word.

There are two formats for redirecting standard output and standard error:

&>word

and

>&word

Of the two forms, the first is preferred.

That made me wonder, why is the first preferred? I see that &>> works, but >>& does not, so the preference makes sense. So why does >>& not work? Is it ambiguous?


Here's what I'm running

$ bash --version
GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)
1
  • On GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17), neither &>> nor >>& work. Commented Aug 6, 2018 at 21:59

1 Answer 1

3

&>dest is unambiguous, whereas >&dest looks like fdup() syntax ...and can be construed as fdup syntax when you have a numeric filename.

Bash, since 4.1 or later, allows the destination of a fdup operation to be parameterized -- thus, not just 2>&1, but also 2>&$stderr_fd. Putting the & after the > puts us into the namespace of syntax used for fdup() operations; keeping it beforehand is unambiguous.

Example: I want to redirect the stdout and stderr of the command cmd into my file. If my file's name is 0, >& causes issues.

  • cmd >& 0 becomes cmd 1>&0. That is, redirect stdout to fd#0.
  • cmd &> 0 becomes cmd > 0 2>&1. That is, redirect stdout to the file named 0, then redirect stderr to fd#1.

[n]>&word is POSIX-standardized; &>word is not found anywhere in the POSIX standard.

The only forms for duplicating existing file descriptors defined by the POSIX standard are [n]<&word and [n]>&word. In the grammar, these are given the token names GREATAND and LESSAND.

There are no POSIX-defined tokens for &> or &< – they are merely syntactic sugar for the commonly used operation of "I don't want to see anything on my screen", or "send stdout and stderr to a file".

This is useful, because cmd 2>&1 > myFile - surprisingly to those new to bash - doesn't work as intended for the "clean screen" goal, whereas cmd > myFile 2>&1, does.


So.. why does &>> work when >>& does not? Because whoever wrote &>> didn't feel the need to create an ambiguity, and consciously chose to not allow >>&.

fdup() synonyms with >> would not add value.

To explain a bit more about why [n]>&word synonyms are pointless -- keep in mind that the difference between >bar and >>bar is the presence of the O_APPEND flag and absence of O_TRUNC in the flags argument to open(). However, when you're providing a file descriptor number -- and thus performing an fdup() from an old FD number to a new one -- the file is already open; the flags thus cannot be changed. Even the direction -- > vs < -- is purely informational to the reader.

5
  • I failed to mention that I'm reading the part of the man page from "Redirecting Standard Output and Standard Error", a subsection of "Redirection". &>word is syntactic sugar for >word 2>&1. I'm going to update my question Commented Aug 6, 2018 at 22:44
  • The semantics of this are subtle... the special case of >& and &> perform 2 redirections, sending both stdout and stderr to the file. The syntax of >& is too similar to the actual bash redirection language, old_out_fd>&new_out_fd, and thus can be confusing. Whereas the &>, with its deliberate swapping of order, cannot be confused as easily. Commented Aug 6, 2018 at 22:56
  • Yes, I agree that those things are true, but I thought the answer already made them clear. Commented Aug 6, 2018 at 23:02
  • Let us continue this discussion in chat. Commented Aug 6, 2018 at 23:05
  • Re cmd 2>&1 >myFile, redirections are processed left-to-right; so in that order, you first make FD 2 point to the original FD 1, then you change FD 1. If FDs 1 and 2 pointed to the same destination in the first place, then 2>&1 did nothing. Commented Aug 7, 2018 at 0:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.