如何将重定向符号指定给变量以组装命令行



我有两个BASH脚本,它们启动我通常使用的程序,这些程序带有公共参数,使用命令和参数的变量。调用显示在末尾,如下所示:

$PROGRAM $ARG1 $ARG2 &

现在,我想在默认情况下将输出重定向到stderr,并将stdout重定向到/dev/null。我希望能够通过切换到脚本来禁用它(-v=verbose)。但是,如果我尝试将"2>&1 > /dev/null"分配给一个var,比如REDIRECTION(如果指定了verbose,则清除它),并尝试调用如下:

$PROGRAM $ARG1 $ARG2 $REDIRECTION &

重定向指令作为参数传递给程序。有办法做到这一点吗?或者,我必须使用我的解决方案,即有两个独立的调用行,一个带有重定向指令,另一个没有重定向指令,这取决于"详细程度"?

一个选项是使用eval内置函数,它像Bash命令一样处理参数,处理重定向运算符之类的事情。然而,eval是非常危险的,因为它会重新处理所有的参数,即使是已经正确处理的参数,如果不完美地,这可能会导致奇怪或不安全的行为。

由于两个版本的命令之间唯一有问题的区别是是否存在重定向,因此更好的选择是使用exec内置。此命令:

exec >/dev/null 2>&1

将shell脚本的剩余部分的STDOUT和STDERR重定向到/dev/null。此命令:

[[ "$IS_VERBOSE" ]] || exec >/dev/null 2>&1

将运行exec >/dev/null 2>&1,除非$IS_VERBOSE为非空,在这种情况下它什么也不做。(您可以将[[ "$IS_VERBOSE" ]]替换为您已经用于检测详细程度的任何类型的条件表达式。)

所以,你想要的是这样的东西:

(
[[ "$IS_VERBOSE" ]] || exec >/dev/null 2>&1
"$PROGRAM" "$ARG1" "$ARG2" &
)

括号中的( ... )用于设置子shell,因此exec命令(如果运行)只影响到)

(顺便说一句,注意我把你的2>&1 > /dev/null改成了> /dev/null 2>&1:订单很重要。)

与其尝试将shell语法编码到参数中,不如将每个重定向运算符的默认目的地放在参数中,并允许一个方法来覆盖默认目的地。

# A little bash-specific, but appropriate defaults should exist for the shell
# of your choice.
STDOUT=/dev/stdout
STDERR=/dev/stderr
if some-test; then
STDOUT=some-other-file
fi
if some-other-test; then
STDERR=different-file
fi
$PROGRAM $ARG1 $ARG2 > $STDOUT 2> $STDERR

您可以构建任何您喜欢的命令行,然后使用eval执行它:

line="echo hello"
if ....
line="$line > junk.out"
fi
eval $line

(但我可能会选择你建议的更容易阅读和理解的2行方法…)

相关内容

  • 没有找到相关文章