如何使用Bash将stdout和stderr重定向并附加到文件?


1533

要将stdout重定向到Bash中的截断文件,我知道使用:

cmd > file.txt

为了重定向Bash中的stdout,将其附加到文件中,我知道要使用:

cmd >> file.txt

要将stdoutstderr都重定向到截断的文件,我知道使用:

cmd &> file.txt

如何将stdoutstderr都重定向到文件?cmd &>> file.txt没有为我工作。


37
我想指出&> outfile是Bash(和其他)特定的代码,而不是可移植的。可移植性的方式(类似于附加答案)一直是而且仍然是> outfile 2>&1
TheBonsai

Answers:


1996
cmd >>file.txt 2>&1

Bash执行从左到右的重定向,如下所示:

  1. >>file.txtfile.txt以追加模式打开并在stdout那里重定向。
  2. 2>&1:重定向stderrstdout当前要去哪里”。在这种情况下,这是在附加模式下打开的文件。换句话说,&1重用stdout当前使用的文件描述符。

33
很棒!但是有什么办法可以理解这一点,还是应该像原子bash构造那样对待它?
flybywire

181
这是简单的重定向,重定向语句像往常一样从左到右进行评估。>>文件:红色。STDOUT到文件(追加模式)(1 >>文件的缩写)2>&1:红色。STDERR到“ stdout所在的位置”注意,“将STDERR重定向到STDOUT”的解释是错误的。
TheBonsai

31
它说:“将输出(stdout,文件描述符1)附加到file.txt上,并将stderr(文件描述符2)发送到与fd1相同的位置”。
暂停,直到另行通知。

2
@TheBonsai但是,如果我需要将STDERR重定向到另一个文件但追加,该怎么办?这可能吗?
2013年

41
如果您这样做cmd >>file1 2>>file2,应该可以实现您想要的。
Woodrow Douglass 2013年

367

有两种方法可以执行此操作,具体取决于您的Bash版本。

经典且可移植(Bash pre-4)的方式是:

cmd >> outfile 2>&1

Bash 4开始的一种非便携式方式是

cmd &>> outfile

(模拟到&> outfile

为了获得良好的编码风格,您应该

  • 确定是否要考虑便携性(然后使用经典方式)
  • 确定是否需要移植甚至是Bash pre-4的可移植性(然后使用经典方法)
  • 无论使用哪种语法,都不要在同一脚本中更改它(混乱!)

如果您的脚本已经以#!/bin/sh(无论是否有意)开头,那么Bash 4解决方案(通常是任何特定于Bash的代码)就不可行了。

还请记住,Bash 4 &>>只是较短的语法-它没有引入任何新功能或类似功能。

语法(除其他重定向语法外)在此处描述:http : //bash-hackers.org/wiki/doku.php/syntax/redirection#appending_redirected_output_and_error_output


8
我更喜欢&>>,因为它与&>和>>一致。读取“将输出和错误附加到此文件”比“将错误发送输出以将输出附加到此文件”更容易。请注意,尽管Linux通常具有bash的当前版本,但在撰写本文时,OS X仍需要通过自制软件等手动安装
bash4。– mikemaccana

我更喜欢它,因为它更短,每行只有tweoi个地方,例如zsh从“&>>”中得出什么?
菲利普

同样要注意的是,在cron作业中,即使系统具有Bash 4,也必须使用4之前的语法
。– hyperknot

5
@zsero cron根本不使用bash ...它使用sh。您可以通过添加SHELL=/bin/bashcrontab -e文件来更改默认Shell 。
雷·福斯

89

在Bash中,您还可以显式指定重定向到其他文件:

cmd >log.out 2>log_error.out

追加为:

cmd >>log.out 2>>log_error.out

6
使用第一个选项将两个流重定向到同一文件将导致第一个流在第二个流的“顶部”写入,从而覆盖部分或全部内容。使用cmd >> log.out 2> log.out
Orestis P.

3
感谢您的接见;你是对的,一个会破坏另一个。但是,您的命令也不起作用。我认为写入同一个文件的唯一方法是像以前那样cmd >log.out 2>&1。我正在编辑我的答案以删除第一个示例。
亚伦·R.

65

在Bash 4(以及ZSH 4.3.11)中:

cmd &>>outfile

开箱即用


2
@all:这是一个很好的答案,因为它可以与bash一起使用并且很简短,所以我进行了编辑以确保它明确提及bash。
mikemaccana

10
@mikemaccana:TheBonsai的答案显示了自2009
jfs


25

尝试这个

You_command 1>output.log  2>&1

您对&> x.file的用法确实可以在bash4中使用。对此表示抱歉:(

这里有一些其他提示。

0、1、2 ... 9是bash中的文件描述符。

0代表stdin,1代表stdout,2代表stderror。3〜9可用于其他任何临时用途。

可以使用运算符>>>(附加)将任何文件描述符重定向到其他文件描述符或文件。

用法:< 类file_descriptor > > < 文件名 | &file_descriptor >

请参考http://www.tldp.org/LDP/abs/html/io-redirection.html


您的示例将执行与OP要求不同的操作:将stderr的stderr重定向You_command到stdout,并将stdout 重定向You_command到file output.log。此外,它不会追加到文件中,但会覆盖它。
pabouk

正确:对于所有其他文件,文件描述符可以是大于3的任何值。
Itachi 2014年

5
您的答案显示了最常见的输出重定向错误:将STDERR重定向到STDOUT当前指向的位置,并且仅在将STDOUT重定向到文件之后。这不会导致STDERR重定向到同一文件。重定向的顺序很重要。
Jan Wikholm'1

1
这是否意味着,我应该首先将STDERROR重定向到STDOUT,然后将STDOUT重定向到文件。 1 > output.log 2>&1
Quintus.Zhou,2015年

1
@ Quintus.Zhou Yup。您的版本将err重定向到out,同时又重定向到文件。
Alex Yaroshevich 2015年

11

令我惊讶的是,近十年来,还没有人发布这种方法:

如果使用的bash较旧版本&>>不可用,您还可以执行以下操作:

(cmd 2>&1) >> file.txt

这产生一个子shell,所以它比传统方法效率较低cmd >> file.txt 2>&1,并因此会为命令是需要修改目前的外壳不工作(例如cdpushd),但这种方法感觉更自然和可以理解的对我说:

  1. 将stderr重定向到stdout。
  2. 通过附加到文件来重定向新的标准输出。

同样,括号消除了任何歧义的顺序,特别是如果您想将stdout和stderr用管道传递给另一个命令时,尤其如此。


此实现导致系统运行一个额外的过程。使用语法cmd >> file 2>&1可在所有Shell中使用,并且不需要额外的进程即可运行。
Mikko Rantalainen

@MikkoRantalainen我已经解释过,它产生一个子shell,效率较低。这种方法的重点是,如果效率不是大问题(很少如此),那么这种方法更容易记住并且更容易出错。
jamesdlin
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.