118

I was a little confused by this expression:

gcc -c -g program.c >& compiler.txt

I know &>filename will redirect both stdout and stderr to file filename. But in this case the ampersand is after the greater than sign. It looks like it's of the form M>&N, where M and N are file descriptors.

In the snippet above, do M=1 and N='compiler.txt'? How exactly is this different from:

gcc -c -g program.c > compiler.txt     (ampersand removed)

My understanding is that each open file is associated with a file descriptor greater than 2. Is this correct?

If so, is a file name interchangeable with its file descriptor as the target of redirection?

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
contrapositive
  • 1,381
  • 2
  • 10
  • 11

3 Answers3

133

This is the same as &>. From the bash manpage:

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.  This is semantically equiva-
lent to

       >word 2>&1
Denilson Sá Maia
  • 47,466
  • 33
  • 109
  • 111
jordanm
  • 33,009
  • 7
  • 61
  • 76
  • 13
    I feel foolish. I spent a bunch of time reading other sources and it was right there in the manpage. – contrapositive Jun 29 '12 at 03:32
  • It goes on to say "Of the two forms, the first is preferred. This is semantically equivalent to `>word 2>&1`" – Dennis Williamson Jun 29 '12 at 03:48
  • 3
    `>&` is the syntax used by csh and tcsh to redirect both stdout and stderr. That's probably why bash accepts it. – Keith Thompson Jun 29 '12 at 05:46
  • 4
    Does this mean that `&>word` and `>word 2>&1` are semantically equivalent? The antecedent to "This" is not clear to me. – geneorama Mar 11 '15 at 16:04
  • @geneorama yes, that is the case. "This" in the post was referring to `>& word` though. – jordanm Mar 11 '15 at 16:08
  • Ah, `&>word` and `>word` are *nearly* the same because both standard out and standard error are redirected to word. However `&>word` and `>word 2>&1` are *exactly* the same because of how they will be written to the console. – geneorama Mar 11 '15 at 16:36
  • 12
    @geneorama `&>word`, `>word 2>&1`, *and* `>&word` are exactly the same. – jordanm Mar 11 '15 at 17:28
  • @jordanm I was trying to point out that `>word` is different from the others. In fact, I think that `>word`, `1>word`, and `1>word2>2` are all exactly the same. – geneorama Mar 11 '15 at 17:46
  • 1
    Now I realize that I made a mistake before based on what I read elsewhere. `>` only redirects standard out. `>` does not redirect error. (I should probably redirect my future comments to `/dev/null`) – geneorama Mar 11 '15 at 17:53
  • what does "&" do here? – 4t8dds Mar 24 '21 at 03:02
  • @MichaelWang Nothing on it's own. it's part of the `&>` and `>&` syntaxes. – jordanm Mar 24 '21 at 15:07
25

&> vs >&: the preferred version is &> (clobber)

Regarding:

  • &>
  • >&

both will clobber the file - truncate the file to 0 bytes before writing to it, just like > file would do in the STDIN-only case.

However, the bash manual Redirections section adds that:

Of the two forms, the first is preferred. This is semantically equivalent to

>word 2>&1

When using the second form, word may not expand to a number or -. If it does, other redirection operators apply (see Duplicating File Descriptors below) for compatibility reasons.

(Note: in zsh both are equivalent.)

It's very good practice to train your fingers to use the first (&>) form, because:

Use &>> as >>& is not supported by bash (append)

There's only one append form:

The format for appending standard output and standard error is:

&>>word

This is semantically equivalent to

>>word 2>&1

(see Duplicating File Descriptors below).

Note:

  • The clobber usage of &> over >& in the section above is again recommended given that there is only one way for appending in bash.
  • zsh allows both &>> and >>& forms.
Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
Tom Hale
  • 40,825
  • 36
  • 187
  • 242
2

Slightly off-topic, but this is why I stick to the long form like >/dev/null 2>&1 all the time. That is confusing enough for people who do it backwards in things like cron without adding >&, &>, >>&, &>>, ... on top of it. I frequently need to add notes in crontab -l reminding people that "2>&1 > /dev/null" is not a best practice.

As long as you remember that any "final destination" is given first, then it should be the same syntax on any Unix or Unix-like system using any Bourne-like shell, appending or otherwise. Plus, since &> is effectively a Bash-ism (may have originated in csh? don't recall, but it is not POSIX either way), it is not always supported on locked-down commercial UNIX systems.

Kajukenbo
  • 109
  • 1
  • 4