我有几个BASH脚本使用命令和参数的变量来启动我经常使用的常见参数的程序。调用最终出现在这样:
$PROGRAM $ARG1 $ARG2 &
现在我想默认将输出重定向到stderr并将stdout重定向到/dev/null
。我希望能够通过切换到脚本(-v
= verbose)来禁用它。但是如果我尝试将"2>&1 > /dev/null"
分配给var,比如REDIRECTION
,(如果指定了详细信息则清除它)并尝试调用如下:
$PROGRAM $ARG1 $ARG2 $REDIRECTION &
重定向指令作为参数传递给程序。有没有办法做到这一点?或者我是否必须使用我的解决方案,即有两个单独的调用行,一个有一个没有重定向指令,一个取决于“详细程度”?
答案 0 :(得分:4)
一个选项是使用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
:订单很重要。)
答案 1 :(得分: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
答案 2 :(得分:0)
您可以构建您喜欢的任何命令行,然后使用eval执行它:
line="echo hello"
if ....
line="$line > junk.out"
fi
eval $line
(我可能会选择你认为更容易阅读和理解的2行方法......)