256

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.

Det
  • 2,682
  • 2
    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. – mirabilos Feb 27 '14 at 13:56
  • I've also seen ^ /dev/null what does that do? – balupton Feb 24 '17 at 00:57

3 Answers3

308

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.

slm
  • 369,824
  • 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)? – Det Apr 06 '13 at 14:38
  • 3
    There should be no performance difference. – slm Apr 06 '13 at 14:38
  • 6
    &> 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. – Stéphane Chazelas Oct 24 '14 at 09:26
  • 2
    Update: about the performance issue, that's also confirmed here: http://unix.stackexchange.com/questions/163955/is-more-efficient-than-dev-null – Det Apr 16 '16 at 14:24
  • 1
    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 – Olivier Dulac Jan 20 '17 at 16:52
  • @OlivierDulac - should we put a warning in the answer about this? – slm Jan 20 '17 at 19:06
  • @slm I believe you should, with a link to Stéphane's answer? – Olivier Dulac Jan 20 '17 at 20:40
  • What is rc as mentioned by Stéphane? – balupton Feb 24 '17 at 00:49
  • What does ^ /dev/null do? – balupton Feb 24 '17 at 01:04
  • 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 May 01 '17 at 14:23
  • @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"." – slm May 01 '17 at 17:10
  • 1
    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. – DrBeco May 01 '17 at 18:45
  • @OlivierDulac you linked the same exact question. – Det May 25 '17 at 17:47
  • @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 – Olivier Dulac May 25 '17 at 17:56
16

This is for redirecting the STDERR & STDOUT:

  • 2>/dev/null

    Redirect STDERR to /dev/null (prevent from showing up on console)

  • |&

    Redirect STDERR and STDOUT to STDIN of piped command (cmd1 |& cmd2)

  • &>/dev/null

    Redirect both STDERR & STDOUT to /dev/null (nothing shows up on console)

  • >/dev/null

    Redirect STDOUT to /dev/null (only STDERR shows on console)

  • 2>&-

    Is for closing a file descriptor used with redirection

These are all standard redirection methods for the Bourne shells.

Lesmana
  • 27,439
BriGuy
  • 3,211
  • 1
  • 15
  • 20
8

Consider this an addendum to the selected answer. You may want to know which forms are POSIX and which are not.

Two POSIX forms are involved:

2.7.2 Redirecting Output

The two general formats for redirecting output are:

[n]>word

[n]>|word

where the optional n represents the file descriptor number. If the number is omitted, the redirection shall refer to standard output (file descriptor 1).

Output redirection using the '>' format shall fail if the noclobber option is set (see the description of set -C) and the file named by the expansion of word exists and is a regular file. Otherwise, redirection using the '>' or ">|" formats shall cause the file whose name results from the expansion of word to be created and opened for output on the designated file descriptor, or standard output if none is specified. If the file does not exist, it shall be created; otherwise, it shall be truncated to be an empty file after being opened.

-

2.7.6 Duplicating an Output File Descriptor

The redirection operator:

[n]>&word

shall duplicate one output file descriptor from another, or shall close one. If word evaluates to one or more digits, the file descriptor denoted by n, or standard output if n is not specified, shall be made to be a copy of the file descriptor denoted by word; if the digits in word do not represent a file descriptor already open for output, a redirection error shall result; see Consequences of Shell Errors. If word evaluates to '-', file descriptor n, or standard output if n is not specified, is closed. Attempts to close a file descriptor that is not open shall not constitute an error. If word evaluates to something else, the behavior is unspecified.

Therefore:

Function      POSIX-compat    POSIX 
2>&-          Yes             close 
2>/dev/null   Yes             redir
2>&1          Yes             dup 
|&            No              
&>/dev/null   No
>/dev/null    Yes             redir
>&/dev/null   ?               ?dup

The last line is not in the original question, but it works without complaint in bash. (Also works with /dev/tty substituted for /dev/null).