43

There are two forms of redirection the standard output and standard error into standard output. But which one is better? and why the &> is considered the perfect?

I can't find what is the differences so that many tutorials and even bash manual state that &> is better!

So Why shall I use &> and not 2>&1

Mainly using bash shell


EDIT: Thanks for commentors

Only >& works in csh or tcsh

In ksh only 2>&1 works.

dash use >file 2>&1 redirection only

Then which one to use to ensure my script is compatible with other systems whatever the used shells are!

10
  • the better one is what does what you need to do. these do very different things. which shell are you using?
    – Skaperen
    Jun 11, 2015 at 10:34
  • @Skaperen using bash
    – Maythux
    Jun 11, 2015 at 10:35
  • 1
    what do you want to accomplish?
    – Skaperen
    Jun 11, 2015 at 10:39
  • I just want to know what is the differences, What I want is dont in both but i just need to know if the is a difference so that once is preffred over other
    – Maythux
    Jun 11, 2015 at 10:41
  • 3
    &> somewhere is just bash shorthand for > somewhere 2>&1: in the words of the bash manual, they are "symantically equivalent" Jun 11, 2015 at 10:55

4 Answers 4

34

Bash's man page mentions there's two ways to redirect stderr and stdout: &> file and >& file. Now, notice that it says both stderr and stdout.

In case of this >file 2>&1 we are doing redirection of stdout (1) to file, but then also telling stderr(2) to be redirected to the same place as stdout ! So the purpose may be the same, but the idea slightly different. In other words "John, go to school; Suzzie go where John goes".

What about preference ? &> is a bash thing. So if you're porting a script, that won't do it. But if you're 100% certain your script will be only working on system with bash - then there's no preference

Here's an example with dash , the Debian Amquist Shell which is Ubuntu's default.

$ grep "YOLO" * &> /dev/null
$ grep: Desktop: Is a directory
grep: Documents: Is a directory
grep: Downloads: Is a directory
grep: Music: Is a directory
grep: Pictures: Is a directory
grep: Public: Is a directory
grep: Templates: Is a directory
grep: Videos: Is a directory
grep: YOLO: Is a directory
grep: bin: Is a directory

As you can see, stderr is not being redirected

To address your edits in the question, you can use if statement to check $SHELL variable and change redirects accordingly

But for most cases > file 2>&1 should work


In more technical terms, the form [integer]>&word is called Duplicating Output File Descriptor, and is a feature specified by POSIX Shell Command Language standard, which is supported by most POSIX-compliant and Brourne-like shells.

See also What does & mean exactly in output redirection?

6
  • Then what happens when using on some other shells?
    – Maythux
    Jun 11, 2015 at 10:56
  • zsh supports &> .... @Maythux In shells that do not support &> e.g. dash you need to use the trivial >file 2>&1 redirection..
    – heemayl
    Jun 11, 2015 at 10:58
  • Then Which one to use if I want to be sure my script will be compatible with different shells
    – Maythux
    Jun 11, 2015 at 10:59
  • 3
    @Maythux Use >file 2>&1 . This work on all the shells Jun 11, 2015 at 11:01
  • 1
    @TSJNachos117 shells set in /etc/passwd for each user are interactive shells. System scripts are usually for dash unless otherwise specified. As for what is default, it's determined by what is symlinked to /bin/sh In Ubuntu's case that's dash. In RHEL it's is bash, in FreeBSD it is tcsh source and another source Jul 17, 2016 at 1:15
10

I would generally recommend following the Bourne-again SHell's way of doing things, since bash is arguably the most popular Unix shell out there. Bash typically uses either &> or 2>&1. IMHO, neither is "perfect", so I recommend forgetting about that nonsense. Realistically, which one you should use depends on what you are trying to do.

2>&1 merges stderr with stdout, which can be useful if, for example, you want to pipe stderr text. So, for example, if you want to see if a program prints a certain stderr message, but don't want your screen filled with (presumably) unimportant garbage, you could do something like program 2>&1 | grep crashed, which will search the stdout and stderr from a program called "program" for the word "crashed".

On the other hand, if you don't want a program to print anything at all, you could simply run program &> /dev/null, which will redirect both stderr and stdout to /dev/null, a special file which magically makes things disappear. Or, if you want to save the output of a program (perhaps to report a bug or something), you could redirect both stderr and stdout to a file: program &> log.txt will redirect all data to a file called "log.txt". If you wanted to, you could redirect the stdout and stderr via program 2> log.txt > log.txt or program 2>&1 | cat > log.txt, both of which would have the same effect as using &>. If you do something like program 2>&1 > file, only stdout will be redirected, but stderr can still be piped to another program, such as cat, which could be redirected as shown above. However, typing &> is easier than any of the above examples, since it involve typing fewer characters (and it's a bit easier for human beings to read). Do note that program 2> log.txt > log.txt might be more likely to work on non-bash shells.

PS: if you are worried about people using other shells, there's something you can add to be first line of your script called a "magic number", or "shebang". This is essentially a way to make sure other computers (particularly those running Unix-like operating systems) know which program to use to execute a script. Different scripts use different shebangs. A shebang for a bash script looks like this:

#!/bin/bash

If you use the above as the first line of a given script, bash will generally be used to execute said script. This will make it much more difficult for someone to accidentally execute the script with the wrong shell.

PS: I'm not going to lie: up till now, I didn't know one could use >&, but, as far as bash goes, it seems to do the same as &>. You learn something new everyday.

4
  • While I do agree with you about use of #! line to explicitly request bash , it is not always available on other systems. Very often developers/sysadmins have to write portable scripts for systems on which bash may not be available and it may not be under their control to install bash . The >file 2>&1 is just much portable. Jul 17, 2016 at 2:29
  • You made a reversal error above, which does not produce the result you claim or want. Redirect stderr to stdout, then redirect stdout leaves stderr on the original stdout.
    – ubfan1
    Jul 17, 2016 at 2:48
  • Serg: I didn't mean to imply bash was universal. However, I think more people are using it than say (t)csh. If you don't know what someone else is using, and have to make a blind guess, bash is probably your best bet. Also, I generally don't know about portability, since I only use bash. The fact that >file 2>&1 is more portable is good to know. I'll make an edit to reflect that. Jul 23, 2016 at 2:08
  • Ubfan1, thanks for the info. I would never have guessed in a million years that bash wouldn't redirect stderr to a file in that case. I've just edited my answer to prevent others from making the same mistake. Jul 23, 2016 at 2:16
7

So Why shall I use &> and not 2>&1

2>&1 is standard Bourne/POSIX shell.

&> is a bash extension and not de jure standard.

If you write scripts using bash extensions, sooner or later you're going to encounter head-scratching failures with cryptic syntax error messages because they're being run in a standard shell.

4

From Bash Reference Manual -> 3.6.4 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 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.

Also good to refer to Greg's wiki on Input And Output -> 4.2. File Descriptor Manipulation:

For convenience, Bash also makes yet another form of redirection available to you. The &> redirection operator is actually just a shorter version of what we did here [ 2>&1 ]; redirecting both stdout and stderr to a file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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