&>和2>&1有什么区别


30

有两种形式重定向的标准输出标准错误标准输出。但是哪个更好?为什么&>认为完美?

我找不到什么区别,因此许多教程,甚至bash手册状态 &>都更好!

所以,我为什么要使用&>而不是2>&1

主要使用bash外壳


编辑:感谢评论员

仅>&可在csh或tcsh中使用

在ksh中,只有2>&1有效。

短划线使用>文件2>&1重定向

然后使用哪一个来确保我的脚本与其他系统兼容,无论使用的shell是什么!


更好的是您需要做什么。这些做的事情截然不同。您正在使用哪个外壳?
Skaperen 2015年

@skaperen使用bash
Maythux 2015年

1
做什么,你要完成?
Skaperen 2015年

我只想知道两者之间有什么不同,我只想知道两者之间没有什么不同,但我只想知道两者之间是否存在差异,以便一次超越其他
Maythux 2015年

2
&> somewhere只是bash的简写> somewhere 2>&1:用bash手册的话来说,它们 “在符号上是等效的”
steeldriver,2015年

Answers:


23

Bash的手册页提到了重定向stderr和stdout的两种方法: &> file>& file。现在,请注意它同时显示stderr和stdout。

在这种情况下,>file 2>&1我们正在将stdout(1)重定向到文件,然后还要告诉stderr(2)重定向到与stdout相同的位置!因此目的可能是相同的,但想法略有不同。换句话说,“约翰,去上学;苏奇去约翰去的地方”。

那么偏好呢?&>是一bash件事。因此,如果要移植脚本,则不会这样做。但是,如果您100%确定您的脚本只能在具有bash的系统上运行-那么就没有偏好了

这是dashDebian Amquist Shell 的示例,这是Ubuntu的默认设置。

$ 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

如您所见,stderr没有被重定向

要解决问题中的修改,可以使用if语句检查$ SHELL变量并相应地更改重定向

但在大多数情况下> file 2>&1应该可以工作


用更专业的术语来说,该格式[integer]>&word称为Duplicating Output File Descriptor,是POSIX Shell命令语言标准指定的功能,大多数POSIX兼容外壳和类似Brourne的外壳都支持该功能。

另请参见输出重定向中的确切含义是什么?


那么在其他一些shell上使用时会发生什么呢?
Maythux 2015年

zsh支持&>.... @Maythux在不支持的shell中,&>例如,dash您需要使用琐碎的>file 2>&1重定向
。–

然后,如果我想确保我的脚本可以与不同的shell兼容,则使用哪一个脚本
Maythux 2015年

3
@Maythux使用>file 2>&1。这项工作适用于所有炮弹
Sergiy Kolodyazhnyy

1
/etc/passwd为每个用户设置的@ TSJNachos117 shell 是交互式shell。dash 除非另有说明,否则系统脚本通常用于。至于默认值,则由/bin/sh与之链接的符号决定。在Ubuntu的情况下为dash。在RHEL中bash,它是tcsh ,在FreeBSD中,它是源,也是另一个源
Sergiy Kolodyazhnyy

6

我通常建议遵循Bourne-again SHell的处理方式,因为bash可以说是目前最受欢迎的Unix shell。Bash通常使用&>2>&1。恕我直言,两者都不是“完美的”,所以我建议您不要再胡说。实际上,应该使用哪一个取决于您要执行的操作。

2>&1将stderr与stdout合并,例如,如果您希望通过管道传递stderr文本,则该功能很有用。因此,例如,如果您想查看某个程序是否输出特定的stderr消息,但又不想让屏幕上充满(大概)不重要的垃圾,则可以执行类似的操作program 2>&1 | grep crashed,它将从程序中搜索stdout和stderr称为“崩溃”一词的“程序”。

另一方面,如果您根本不希望程序打印任何内容,则只需运行即可program &> /dev/null,它将stderr和stdout都重定向到/ dev / null,这是一个神奇的特殊文件,可以使一切消失。或者,如果您想保存程序的输出(也许是报告错误或类似的内容),则可以将stderr和stdout都重定向到一个文件:program &> log.txt将所有数据重定向到一个名为“ log.txt”的文件。如果您愿意,可以通过program 2> log.txt > log.txt或重定向stdout和stderr program 2>&1 | cat > log.txt,两者的作用与使用相同&>。如果执行类似的操作program 2>&1 > file,则只有stdout会被重定向,但是stderr仍然可以通过管道传递到另一个程序,例如cat,可以如上所示进行重定向。但是,键入&>比上面的任何示例都更容易,因为它涉及到键入更少的字符(并且人类更容易阅读)。请注意,这program 2> log.txt > log.txt可能更适用于非bash外壳。

PS:如果您担心其他人会使用其他Shell,则可以在脚本的第一行添加一些名称,即“魔数”或“ shebang”。本质上,这是确保其他计算机(尤其是运行Unix操作系统的计算机)知道使用哪个程序执行脚本的方法。不同的脚本使用不同的shebang。bash脚本的shebang看起来像这样:

#!/bin/bash

如果将以上内容用作给定脚本的第一行,则通常将使用bash执行该脚本。这将使某人使用错误的Shell意外执行该脚本变得更加困难。

PS:我不会撒谎:到目前为止,我还不知道有人可以使用它>&,但是就bash而言,它似乎与相同&>。你每天学习新的东西。


尽管我确实同意您使用#!line来显式请求bash,但它在其他系统上并不总是可用。开发人员/系统管理员通常不得不为bash可能不可用且可能不受其控制的系统编写可移植脚本bash。该>file 2>&1只是很多便携。
Sergiy Kolodyazhnyy

您在上面犯了一个反转错误,该错误不会产生您要求或想要的结果。将stderr重定向到stdout,然后重定向stdout将stderr保留在原始stdout上。
ubfan1

Serg:我并不是说bash是普遍的。但是,我认为使用它的人比说(t)csh多。如果您不知道别人在使用什么,并且不得不盲目猜测,那么bash可能是您最好的选择。另外,我通常不了解可移植性,因为我只使用bash。>file 2>&1更便携的事实是众所周知的。我将进行编辑以反映这一点。
TSJNachos117 '16

Ubfan1,感谢您的信息。我永远不会想到,在一百万年后bash不会将stderr重定向到文件。我刚刚编辑了答案,以防止其他人犯同样的错误。
TSJNachos117 '16

4

Bash参考手册-> 3.6.4重定向标准输出和标准错误

此结构允许将标准输出(文件描述符1)和标准错误输出(文件描述符2)都重定向到名称为word扩展的文件。

重定向标准输出和标准错误有两种格式:

&>word

>&word

在两种形式中,第一种是优选的。这在语义上等同于

>word 2>&1

当使用第二种形式时,单词可能不会扩展为数字或'-'。如果是这样,出于兼容性原因,将应用其他重定向操作符(请参阅下面的“复制文件描述符”)。

还可以参考Greg的Wiki,有关输入和输出-> 4.2。文件描述符操作

为了方便起见,Bash还为您提供了另一种重定向形式。&>重定向运算符实际上只是我们在此所做的简短版本[ 2>&1];。将stdout和stderr都重定向到文件。


4

那么为什么我要使用&>而不是2>&1

2>&1 是标准的Bourne / POSIX外壳。

&>是bash扩展,不是法律标准。

如果您使用bash扩展名编写脚本,则迟早会遇到带有隐式语法错误消息的抓头错误,因为它们在标准Shell中运行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.