无法重定向到存储在变量中的文件描述符

4
编辑注:这个问题经历了几次修改,改变了问题的性质,可能会使旧的评论和答案无效;它的原始标题是“无法将Bash输出重定向到/dev/null”。
我正在尝试创建一个小型的Bash脚本,并且我想实现一个静默模式。基本上,我只想默认隐藏大多数输出,并在使用-v运行时显示所有输出。
因此,在我的脚本开头,我放置了以下代码:
#!/bin/bash
declare output=''
if [ "$1" = -v ]; then
  output="&1"
else
  output="/dev/null"
fi

然后在我的脚本中,我有以下内容:
{
  # whatever commands...
} > $output 2>&1

静默模式很好用。然而,如果我尝试冗长模式,就会生成一个名为 &&1(取决于我的 output 变量)的文件。此外,该文件为空。这不是期望的结果:我希望输出保留在终端上!

这是因为我重定向的顺序有误还是我的变量有问题?编辑:通过将 "&1" 替换为 "/dev/tty",脚本现在完全可行。


4
在发布帖子之前请尝试使用http://shellcheck.net/进行检查。建议将此问题标记为简单的拼写错误并关闭。 - tripleee
谢谢提供链接!然而,即使修正了拼写错误,还存在一个问题:无论详细模式是否开启,输出总是相同的。 - Lupuss
@Lupuss 将stderr也重定向 - 123
3
您可以使用“exec > /dev/null 2>&1”将stdout和stderr永久重定向到/dev/null。 - gniourf_gniourf
2个回答

4

很可能是错误输出被打印出来了。请注意,使用 > /dev/null 只会重定向标准输出,而不会重定向标准错误输出。您可以在重定向标准输出之前使用 2>&1 将标准错误输出重定向到标准输出。类似这样:

{
  # whatever commands...
} > $output 2>&1

现在当我处于“静默”模式下时,它运行得很好,但是在冗长模式下不行 :) - Lupuss
有了后见之明(不幸的是,OP多次更改了问题): 虽然这个答案展示了一种通常有用的技巧——如何将stderr输出发送到与stdout输出相同的目标(重定向)—— 但它没有解决OP问题的最终版本,该问题源于尝试将对文件描述符的重定向存储在变量中,而这是不支持的。 小争议:2>&1并不是在重定向stdout之前重定向stderr;相反,它将stderr重定向到已经重定向的stdout,即在stdout被重定向之后。 - mklement0

0

简而言之

  • 你不能将重定向到文件描述符(在你的情况下是&1)存储在变量中 - 如果这样做,你将创建一个以该名称命名的文件(在你的情况下是一个名为&1的文件)。

  • $output设置为/dev/tty是不明智的,因为这样你就会始终输出到终端,这会阻止捕获文件中的详细输出;例如,script -v > file将无法工作。

  • 采纳gniourf_gniourf在评论中的建议,使用exec代替:exec > /dev/null 2>&1或者使用Bash特定的语法,exec &>/dev/null使剩余的脚本静音。


仅将重定向到文件描述符是有效的:

  • 如果重定向目标是字面值,而不是变量引用。
  • 如果>和目标之间没有空格
date > &1 # !! SYNTAX ERROR: syntax error near unexpected token `&'

date >&1  # OK - but works with a *literal* `&1` only

如果你使用一个变量,那没关系,因为变量内容总是被解释为文件名 - 这就是你没有得到语法错误的原因,而最终得到一个名为&1的输出文件。

output='&1'
date >$output  #  !! Creates a *file* named '&1'.
date > $output #  !! Ditto.

为了解决你的问题,我建议采纳评论中gniourf_gniourf的建议:使用exec
#!/usr/bin/env bash

if [[ $1 == '-v' ]]; then
  : # verbose mode: redirect nothing
else 
  # quiet mode: silence both stdout and stderr
  exec &>/dev/null
fi

echo 'hello'      # will only print with -v specified
echo 'hello' >&2  # ditto

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