Difference between 2>&-, 2>/dev/null, |&, &>/dev/null and >/dev/null 2>&1

  • Just looking for the difference between

    • 2>&-
    • 2>/dev/null
    • |&
    • &>/dev/null
    • >/dev/null 2>&1

    and their portability with non-Bourne shells like tcsh, mksh, etc.

    Note that, while mksh supports `&>` for GNU bash compatibility, it’s strongly encouraged to not use this, as parsing it can break the semantics of existing POSIX scripts, and mksh disables that in POSIX mode already.

    I've also seen `^ /dev/null` what does that do?

  • slm

    slm Correct answer

    8 years ago

    For background:

    • a number 1 = standard out (i.e. STDOUT)
    • a number 2 = standard error (i.e. STDERR)
    • if a number isn't explicitly given, then number 1 is assumed by the shell (bash)

    First let's tackle the function of these. For reference see the Advanced Bash-Scripting Guide.

    Functions

    2>&-

    The general form of this one is M>&-, where "M" is a file descriptor number. This will close output for whichever file descriptor is referenced, i.e. "M".

    2>/dev/null

    The general form of this one is M>/dev/null, where "M" is a file descriptor number. This will redirect the file descriptor, "M", to /dev/null.

    2>&1

    The general form of this one is M>&N, where "M" & "N" are file descriptor numbers. It combines the output of file descriptors "M" and "N" into a single stream.

    |&

    This is just an abbreviation for 2>&1 |. It was added in Bash 4.

    &>/dev/null

    This is just an abbreviation for >/dev/null 2>&1. It redirects file descriptor 2 (STDERR) and descriptor 1 (STDOUT) to /dev/null.

    >/dev/null

    This is just an abbreviation for 1>/dev/null. It redirects file descriptor 1 (STDOUT) to /dev/null.

    Portability to non-bash, tcsh, mksh, etc.

    I've not dealt much with other shells outside of csh and tcsh. My experience with those 2 compared to bash's redirection operators, is that bash is superior in that regard. See the tcsh man page for more details.

    Of the commands you asked about none are directly supported by csh/tcsh. You'd have to use different syntaxes to construct similar functions.

    We have a winner. But so there's no performance difference or some such with `2>&-` vs `2>/dev/null` (other than that some "poorly" written programs don't undrestand `2>&-` correctly)?

    There should be no performance difference.

    `&>` was in `bash` from the start (and breaks Bourne and POSIX compatibility as it means something different there, though is unlikely to be hit). `>&` and `|&` come from `(t)csh` (and it's their only way to redirect stderr). They were in `zsh` from the start and have only been added recently to `bash`. See also `rc` for better designed operators.

    Update: about the performance issue, that's also confirmed here: http://unix.stackexchange.com/questions/163955/is-more-efficient-than-dev-null

    Big warning about the closing one : do NOT use it for stdin, stdout or stderr, see http://unix.stackexchange.com/questions/163955/is-more-efficient-than-dev-null/163959#163959

    @OlivierDulac - should we put a warning in the answer about this?

    @slm I believe you should, with a link to Stéphane's answer?

    What is `rc` as mentioned by Stéphane?

    What does `^ /dev/null` do?

    I've got an anonymous -2 after editing the `2>&1` to clarify it would send it to `N=1` in this case. It is unfair, I can't face my accuser. But the edition is completely fine and helps understanding. I could say `2>&1234` for example, and it would redirect `2` it to `1234`. Moreover, after that, I cannot read from `M`, just from `N`. Ergo the edition: `namely N`. So, please revert back and give me back my 2 points. ;)

    @DrBeco - you should've received a -2 after the original +2 so net 0 change to rep. I rejected this edit since I didn't feel it added anything additional beyond what I wrote. You added this: ", namely "N"." so that my original sentence reads like this:: "The general form of this one is M>&N, where "M" & "N" are file descriptor numbers. It combines the output of file descriptors "M" and "N" into a single stream, namely "N"."

    Hi @slm, thanks for the contact. I'm glad my repo didn't change `(+2-2=0)`. Now, to the edition part, I don't edit much, but in this case I would, because it clarifies that the data after the operation would be at `N`. I've read you answer through, and it is very fine in all aspects. Just this small ambiguity got me thinking, that is why the edition. But ok, feel free to re-add or reject it, as you will. I hope I could explain the point. Keep up the good work.

    @OlivierDulac you linked the same exact question.

    @Det yes, but you were talking about the performance aspect, I was warning about and pointing out the big (and, for me, unknown and unforseeable) problems about closing stdout or err, that Stephane warns about in that same answer

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM