将重定向操作本身的错误重定向

4

假设我当前目录下有一个名为a.txt的文件,它的chmod值为000。

因此,如果我尝试写入该文件,我将会得到以下输出:

> printf "Hello" >> a.txt
-bash: a.txt: Permission denied

我该如何抑制这个输出?我已经尝试在命令后添加2>/dev/null,但这个重定向似乎没有像我最初希望的那样工作。

顺便问一下,您希望程序仍然运行,而不是悄悄地根本没有被调用吗?对于printf来说,显然,如果它无法写入stdout,则运行它是没有意义的;但是我可以想到一些其他有副作用的情况,您实际上可能需要这样做。 - Charles Duffy
@CharlesDuffy 对我的目的而言,这将是一个 bash 脚本,它会隐藏大部分输出并使用打印语句来解释正在发生的事情的一般概念。此 printf 是 if 语句的一部分,如果写入失败,则告知用户已经写入失败,并在退出时使用代码 1 之前与我联系。 - Bob Jones
1
明白了。另外,信息和诊断信息通常应该打印到stderr而不是stdout。这不仅是遵循POSIX约定的问题,还确保您的日志在stdout被管道传输到其他地方时仍然显示在正确的位置,并确保这些日志立即打印而不是缓冲(当打印到非TTY目标时,stdout默认为缓冲 -- 为什么内容在这种情况下不立即显示是我们这里的一个常见问题)。 - Charles Duffy
2个回答

5
如果你希望在运行命令时不仅要从之前的重定向中抑制错误,也要抑制这个人的答案所说的错误消息,那么他的回答是正确的。
如果你只想从重定向本身抑制消息,而不想抑制实际执行过程中的错误消息,那么你需要一个额外的重定向来临时存储stderr的原始值,以便稍后恢复。
printf "Hello" 3>&2 2>/dev/null >>a.txt 2>&3 3>&-

这可以分解为以下步骤:

  • 3>&2 将原始 stderr(FD 2)复制到默认情况下未使用的文件描述符(FD 3)上,创建原始目标的备份。
  • 2>/dev/null 然后将 stderr 指向/dev/null
  • >>a.txt 将 stdout(FD 1)指向a.txt,stderr指向 /dev/null
  • 2>&3 在 FD 2 上复制我们在 FD 3 上的备份,将 stderr 恢复到其原始目标,以便正在运行的程序可以记录错误。
  • 3>&- 删除备份,使文件描述符表看起来像什么都没有做一样。(通常可以安全地省略此步骤 - 大多数行为良好的程序将简单地忽略非标准文件描述符的初始值,除非明确告知要执行其他操作)。

1
优秀的答案。值得注意的是,如果您正在交互式运行,则可能希望简化为:cmd 2> /dev/null > output 2> /dev/tty - William Pursell
很聪明。@thatotherguy的评论对我来说已经足够,但我肯定会记下来以备将来参考! - Bob Jones
1
谢谢!顺便说一句,这是一个很好的第一个问题!内容简洁明了;格式良好,不是我们一遍又一遍看到的FAQ,描述了你尝试过的东西等。 - Charles Duffy

2
重定向是按顺序评估的,因此要想抑制消息,您必须在尝试重定向stdout之前重定向stderr。请保留HTML标签。
printf "Hello" 2> /dev/null >> a.txt

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