bash:使用变量存储stderr | stdout重定向


17

有没有办法通过变量重定向stdout和stderr,例如在脚本中添加命令选项?

例如,我有一个脚本:

#!/bin/bash -x
TEST=">/dev/null 2>&1"
OPT='-p -v'
mkdir $OPT 123/123/123 $TEST

我可以看到OPT被替换为-p没有任何问题,bash将其解释为选项。但是重定向解释为目录名称。

$ ./test.sh 
+ TEST='>/dev/null 2>&1'
+ OPT='-p -v'
+ mkdir -p -v 123/123/123 '>/dev/null' '2>&1'
mkdir: created directory `123/123'
mkdir: created directory `123/123/123'
mkdir: created directory `>/dev'
mkdir: created directory `>/dev/null'
mkdir: created directory `2>&1'

有什么办法可以说bash,$ VAR是重定向的,而不是dirs的名字。

PS。可能是我走错了路,但我想从脚本中生成可选的详细或非详细输出。但是,即使在非详细模式下,我也需要一些输出,因此,我不能仅从脚本中的某些命令重定向整个stdout和stderr。

Answers:


18

另一个解决方案可能是以下方法:

#!/bin/bash

verbose=0

exec 3>&1
exec 4>&2

if ((verbose)); then
  echo "verbose=1"
else
  echo "verbose=0"
  exec 1>/dev/null
  exec 2>/dev/null
fi

echo "this should be seen if verbose"
echo "this should always be seen" 1>&3 2>&4

然后1>&3 2>&4仅将其添加到要查看其输出的命令。


大。这正是我所关注的。谢谢。
急于

我写了一篇文章来解释它是如何工作的
Transang

5

其他答案已经很好地解释了“如何”。我想解决“为什么” OP的代码不起作用的问题。

主题演讲是变量扩展之前标记输出重定向 重定向实际上在变量扩展之后执行的(因此,为什么可以将输出重定向到存储在变量中的文件名),但是Shell会识别重定向,以便在扩展变量之前进行后续处理。

换句话说,一旦变量被扩展,就不能考虑使用重定向字符(<>等),因为外壳程序已经识别出它将要作为重定向处理的命令字符串的哪一部分。

有关更多阅读,请参阅下面列出的步骤1和3:

LESS='+/^SIMPLE COMMAND EXPANSION' man bash

3

它不是将其解释为“目录名称”,>而是被引用,因此按原义进行处理(更具体地说,您正在发送字符串>dev/null 2>&1。解决此问题的唯一方法是使用eval或产生新的shell。

至于问题中提到的“冗长”问题,只需执行以下操作即可:

verbose=1
if (( verbose )); then
    mkdir -v -p /foo
else
    mkdir -p /foo > /dev/null 2>&1
fi

1

您的变量中有很多空格,这些空格将无法正确评估。您将要使用eval来进行设置。

#!/bin/bash -x
TEST=">/dev/null 2>&1"
OPT='-p -v'
eval mkdir $OPT 123/123/123 $TEST

这将允许将$ OPT分为两个参数(-p-v),而不是一个(-p -v)和$ TEST相同。也更改为使用,/dev/null因为dev在当前目录中不太可能有目录。


0

enzotib的答案使用了一些好的文件描述符魔术,但是一个更简单的解决方案是仅使用eval该行(但是,这确实增加了过程开销):

$ rm /tmp/foo
$ ll /tmp/foo
ls: cannot access /tmp/foo: No such file or directory
$ FOO=">/tmp/foo"
$ date $FOO
date: invalid date '>/tmp/foo'
$ cat /tmp/foo
cat: /tmp/foo: No such file or directory
$ eval date $FOO
$ cat /tmp/foo
Thu Dec 13 14:08:17 EST 2018
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.