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

时间:2016-02-11 10:42:00

标签: bash verbosity

编者注::这个问题经历了多次修改,改变了问题的性质,可能使较旧的评论和答案无效;它的原始标题是“无法将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"的输出值,脚本现在可以完全正常工作。

2 个答案:

答案 0 :(得分:4)

很可能是错误输出正在打印。请注意,对于> /dev/null,仅重定向stdout而不重定向stderr。在重定向stdout之前,可以使用2>&1将stderr重定向到stdout。类似的东西:

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

答案 1 :(得分:0)

<强> TL;博士

  • 您无法在变量中将重定向存储到文件描述符(在您的案例中为&1) - 如果您这样做,您将创建取而代之的是一个文件(在你的情况下,一个名为&1的文件)。

  • $output设置为/dev/tty是不明智的,因为然后总是输出到终端,这会阻止捕获文件中的详细输出;例如,script -v > file将无效。

  • 从评论中获取gniourf_gniourf's建议,然后使用execexec > /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

如果您使用变量,那无关紧要,因为变量内容总是被解释为 filename - 这就是您没有得到语法错误的原因,但最后输出的文件名为&1

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

要解决您的问题,我建议您从评论中提出gniourf_gniourf's建议:改为使用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