4

我有几个 BASH 脚本可以启动我常用的程序,这些程序使用命令和参数的变量来使用公共参数。调用出现在最后,如下所示:

$PROGRAM $ARG1 $ARG2 &

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

$PROGRAM $ARG1 $ARG2 $REDIRECTION &

重定向指令作为参数传递给程序。有没有办法做到这一点?或者我是否必须使用我的解决方案,即有 2 个单独的调用行,一个有重定向指令,一个没有重定向指令,具体取决于“详细程度”?

4

3 回答 3

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:顺序很重要。)

于 2012-10-17T23:38:52.777 回答
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
于 2012-10-18T13:01:36.207 回答
0

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

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

eval $line

(但我可能会采用您建议的 2 行方法,因为它更易于阅读和理解......)

于 2012-10-17T23:38:14.493 回答