"&> foo" 和 "> foo 2>&1" 有什么区别?

10

似乎有两种bash惯用语将STDOUT和STDERR重定向到文件:

fooscript &> foo
fooscript > foo 2>&1

有什么区别?在我看来,第一个只是第二个的快捷方式,但我的同事认为,即使出现初始重定向错误,第二个不会产生任何输出,而第一个将在标准输出中显示重定向错误。

编辑:好的...似乎人们没有理解我的问题,所以我会尽力澄清:

是否有人可以给我一个示例,在上面写的两个具体行将产生不同行为的情况?

8个回答

8

bash手册中得知:

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
“语义等价”这个词组可以解决您和同事之间的问题。

6
当你的脚本不是在bash中运行,而是在sh家族的某个更简单的shell中运行时,两行代码的行为会有所不同。例如dash(我相信它被一些Linux发行版用作/bin/sh,因为它比bash更轻量级)。在这种情况下,
fooscript &> foo

这个命令被解释为两个命令:第一个在后台运行fooscript,第二个截断了文件foo。该命令为:

fooscript > foo 2>&1

在前台运行fooscript,并将其输出和标准错误重定向到文件foo。在bash中,我认为这些行始终执行相同的操作。


实际上,在dash中,&>并不是这样工作的——它在后台运行fooscript,但没有重定向任何内容。如果你写了(fooscript &) >foo,那么描述的情况就会发生。 - ephemient
1
你说得对,fooscript的输出并没有被重定向到fooscript &> foo中。相反,一个空命令被重定向到文件foo中。我编辑了我的回复来说明这一点。 - Jouni K. Seppänen

3

根据我的经验,使用2>&1的主要原因是当您想将所有输出附加到文件而不是覆盖文件时。使用&>语法,您无法附加。因此,使用2>&1,您可以编写类似于program >> alloutput.log 2>&1的内容,并将标准输出和标准错误输出附加到日志文件中。


2

&>foo>foo 2>&1 更省事(你不可能把它弄错顺序),而且更少出错,但能达到同样的效果。

2>&1 很令人困惑,因为你需要在 1> 重定向之后放置它,除非 stdout 被重定向到 | 管道,这种情况下它会放在前面...

$ some-command 2>&1 >foo    # 做了意料之外的事
$ some-command >foo 2>&1    # 和这个一样
$ some-command &>foo        # 这个也是一样的
$ some-command >&foo        # 兼容其他 shell,但如果文件名是数字就有问题
$ some-command 2>&1 | less  # 但在这里,重定向要放在管道之前...

1
&> foo # Will take all and redirect all output to foo.

2>&1 # will redirect stderr to stdout.

谢谢,但我问的是"> foo 2>&1"和"&> foo"之间的区别,而不是"2>&1 foo"和"&> foo"。 - Max Cantor
在第一个中,所有输出都发送到 foo。在第二个中,fooscript 将 stdout 发送到 foo,然后 foo 将 stderr 发送到 stdout,并打印到 stdout 指向的位置(通常是控制台)。 - J.J.
是的,但这两个东西有什么区别?有吗?你能举一个情况的例子,它们会产生不同的行为吗? - Max Cantor

1

2>&1 取决于在命令行中指定的顺序。其中 &> 将 stdout 和 stderr 发送到任何地方,2>&1 将 stderr 发送到命令行中该点 stdout 当前 去的地方。因此:

command > file 2>&1

与以下命令不同:

command 2>&1 > file

前者将 stdout 和 stderr 重定向到文件,后者将 stderr 重定向到 stdout 在被重定向到文件之前的位置(在这种情况下,可能是终端)。如果您想要执行以下操作,则此功能非常有用:

command 2>&1 > file | less

在这里,您想使用 less 分页查看 stderr 的输出并将 stdout 的输出存储到文件中。


0
我知道这是一个相当古老的帖子..但分享一下可能会回答问题的内容: * ..会产生不同的行为?
场景: 当您尝试使用"tee"并且想要在bash中使用进程替换来保留退出代码时... someScript.sh 2>&1 >( tee "toALog") # 无法捕获输出到日志
而:
someScript.sh >&> >( tee "toALog") # 没问题!

0

2>&1可能在你不想将stdout重定向到其他位置,而是希望stderr被发送到与stdout相同的位置(比如控制台),尤其是当你运行的命令已经将stderr发送到除控制台以外的其他地方时。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接