如何将"> /dev/null 2>&1"放入一个变量中?

5

我希望它能够正常工作。

if [ $debug = 0 ]; then
   silent=""
else
   silent='> /dev/null 2>&1'
fi

#some command
wget some.url $silent

所以如果设置了$debug,它就会变成:

wget some.url > /dev/null 2>&1

否则,如果$debug未设置为1,则变为:
wget some.url

将"> /dev/null 2>&1"存储在一个变量中不起作用。我应该怎么做?


4
顺便说一下,wget-q 选项提供了您似乎正在寻找的确切功能。 - devnull
1
它不是这样工作的,有很好的理由:将数据(如变量内容)转换为语法(如重定向)是一个安全噩梦。eval 强制执行这一点——这正是为什么你不应该使用 eval 的原因。请参见 http://mywiki.wooledge.org/BashFAQ/048 以获取更多讨论。 - Charles Duffy
这不仅仅是关于wget。我经常需要它。"wget some.url"更像是一个"任何命令"的占位符。 - user28464
4个回答

5
这可能是使用shell函数的一个好借口:
silent() {
    "$@" > /dev/null 2>&1
}

现在您可以通过以下方式运行程序来使其静音:

silent wget some.url

如果你只想有条件地静音事物,那很容易:
silent() {
  if [[ $debug ]] ; then
    "$@"
  else
    "$@" &>/dev/null
  fi
}

3
请使用"$@"而不是$* - dogbane
1
你可以使用以下代码:if [ $debug = 0 ]; then maybesilent=""; else maybesilent=silent; fi ... $maybesilent wget some.url - Gordon Davisson
@GordonDavisson ...但是你为什么要这样做呢?silent函数可以很好地检查标志是否设置。使用字符串拆分来形成命令行,在边角情况下很难预测,即使不是完全邪恶的。如果有人将$IFS设置为i(不寻常,但并非闻所未闻--例如,解析具有奇怪分隔符的文件),那么$maybesilent wget some.url将变成s lent wget some.url,当maybesilent=silent时。 - Charles Duffy

3
你需要使用shell来将变量内容解释为命令行的一部分,而不仅仅是作为传递给可执行文件的字符串参数。查看 eval shell内置命令
注意安全漏洞!

1
为什么要建议使用危险的东西,而不是安全的东西(函数使用)? - Charles Duffy

2
一种稍微不同的方法,但类似这样的应该可以起作用:

if [ $debug = 1 ]; then
   exec > /dev/null
fi

#some command
wget some.url

它有条件地将stdout替换为/dev/null

这里唯一的争议是 $debug 要么用双引号括起来,要么用 [[ ]] 替换 [ ] 以防止在字符串拆分或通配符扩展过程中被解析成单个令牌以外的任何东西。 - Charles Duffy
@CharlesDuffy同意。我故意没有改变任何东西,除了重定向,但这肯定是正确的做法。 - Stephen Darlington

1
使用eval:
eval wget some.url $silent

eval会将参数重新解释为shell命令,而不是调用程序的参数。

要小心,不要在未知或外部输入上运行eval,否则您将面临巨大的安全漏洞。


2
使用 eval 是极其危险的。试着操作一个文件名中带有 $(rm -rf /) 的文件吧... - Charles Duffy
在参数受到严格控制且不包含外部输入的情况下(如本例),它的使用是安全的。 - nneonneo
2
Stack Overflow 的部分目的是成为知识库。在知识库中提供的答案如果在非常狭窄的安全窗口之外使用会带来风险,这使得它成为了一个雷区。此外,你永远不知道你编写的代码将来会如何被更改或更新;当它首次起草时成立的条件可能并不总是成立。 - Charles Duffy

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