无法访问 2>&1:如何将变量内容视为重定向而不是文件名

Cannot access 2>&1: How to treat variable content as a redirection not as filename

如何根据变量内容控制进程输出重定向?我试过以下,但它将 $redirect 的内容视为文件名而不是重定向本身。

$ redirect="2>&1 >/dev/null"
$ ls -la $redirect
ls: cannot access 2>&1: No such file or directory
$ redirect=""
$ ls -la $redirect
total 376
drwx------ 1 wakatana users   4096 Feb  5 15:32 .
drwx------ 1 wakatana users   4096 Feb  2 18:44 ..
-rw------- 1 wakatana users    390 Feb  5 13:34 .bashrc

2>&1的顺序需要颠倒,改成:

$redirect="2>&1 >/dev/null"

$redirect=">/dev/null 2>&1"

编辑:

为了 运行 ls -al 在命令行上,更好的选择是:

$redirect="ls -al >/dev/null 2>&1"
eval $redirect

2>&1放在最后的目的是重定向命令产生的所有错误以及第一次重定向。

ls 错误的发生是因为 shell 在执行参数扩展之前扫描重定向(您可能还会考虑重定向的顺序)并尝试列出两个名为 2>&1>/dev/null,就像您输入 ls '2>&1' '>/dev/null' 一样。做你想做的事情的方法是对所有重定向和替换进行第二次迭代。 eval 内置函数就是这样做的:

 eval ls -la $redirect

非要知道,按照the POSIX shell specification的顺序是

  1. 根据Shell语法规则被识别为变量赋值或重定向的词被保存以供在步骤3和4中处理。

  2. 非变量赋值或重定向的词应为 展开。如果有任何字段在扩展后仍然存在,则第一个 字段应被视为命令名称,其余字段为 命令的参数。

  3. 重定向应按照重定向中的描述执行。

  4. 每个变量赋值都应该进行波浪符扩展、参数扩展、命令替换、算术扩展和 在分配值之前删除引号。

这里有一个不太复杂的重定向示例来说明正在发生的事情:

$ redirect=">file"
$ echo foo $redirect
foo >file
$ eval echo foo $redirect
$ cat file
foo

正如 Etan 指出的那样,如果您不控制 redirect 的确切内容,eval 可能不是合适的解决方案。想象一下 redirect='; rm -rf $HOME' 能做什么。

如果您接受更改命令的顺序,这是一种实现您想要的方法:使用别名。别名通常不受欢迎,而且,如 Bash 手册中所述,对于几乎所有用途,别名都被 shell 函数取代。

我们似乎处于 几乎 突破口:

$ alias redirect='2>&1 > /dev/null'
$ redirect ls
$

没有eval.