使用文件描述符或变量中的文件名进行Bash重定向

11

在我的脚本中,我希望能够根据特定条件将内容写入文件或标准输出。我想知道为什么以下代码在我的脚本中不起作用:

out=\&1
echo "bird" 1>$out

我尝试了不同的引号组合,但是它仍然创建了一个"&1"文件而不是将内容写入标准输出。我该怎么做才能让它按照我想要的方式工作?


你的系统是否支持 out=/dev/stdout? - mob
5个回答

5

eval 的一种可能更安全的替代方法是使用 exec 将目标复制到临时文件描述符中(例如,此示例中的文件描述符 3):

if somecondition; then exec 3> destfile; else exec 3>&1; fi

echo bird >&3

3
@Dennis: 我真的无法理解那个"eval"陈词滥调...似乎在stackoverflow上回答了所有与bash相关的问题 :) 再说一遍,也是第一千次:eval只是一个工具,本身并不会造成风险...这就好比说你必须避免Lisp,因为你可以将Lisp数据视为代码... - Diego Sevilla
1
@Diego:eval 可以是一个有用的工具。但它也存在严重的潜在安全风险。如果你避免使用它,就不必担心那一类特定的风险。通常很容易避免。尽可能采取简单和安全的方法。当你确实需要使用 eval 时,请确保你真正需要它,并正确地对输入进行消毒处理,并采取其他必要步骤以防止问题发生。请参见 BashFAQ/048这个优秀的 SO 问题(支持和反对)。此外,请注意我说的是“最好避免”,而不是“永远不要使用”。 - Dennis Williamson
2
@Dennis:我同意你关于“通用”eval使用的大部分观点。但是,在这种情况下,他控制着所有的代码。在我完全掌控的代码中,避免使用eval是没有意义的... - Diego Sevilla
2
@Diego:在这种情况下,为什么要使用eval,而不是更干净、更易读的exec呢?我相信@Dennis想表达的观点是,只有在没有明显替代方案时才应该使用eval。在这种情况下有更好的选择。 - jabbie
我在自己的脚本中遇到了问题,无法使其正常工作,以下是我不知道为什么要使用的语法:destfile="/some/path"; exec 3>${destfile} - Eliot

3

截至2015年,可以重定向到>&${out}。例如:

exec {out}>&1
echo "bird" 1>&${out}

2
深入解释Diego的回答。有条件地更改stdout的位置。
if [ someCondition ] ; then
  # all output now goes to $file
  exec 1>$file
fi

echo "bird"

或者创建您自己的文件描述符;

if [ someCondition ] ; then
  # 3 points to stdout
  exec 3>&1
else
  # 3 points to a file
  exec 3>$outfile
fi

echo "bird" >&3

源自:csh编程的弊端 - 了解更多重定向技巧,请查看该链接。或者阅读bash手册。


我在自己的脚本中遇到了问题,最后不得不使用完整的变量扩展表示法,例如:destfile="/some/path"; exec 3>${destfile} - Eliot

1

我相当确定这与bash处理命令行的顺序有关。以下内容有效:

export out=\&1
eval "echo bird 1>${out}"

因为变量替换发生在评估之前。


0

尝试使用eval。它应该通过解释$out的值本身来工作:

out='&1'
eval "echo \"bird\" 1>$out"

将在标准输出上打印bird(如果更改out,还会打印到文件中)。

请注意,在eval字符串中放置什么要小心。注意内部引号的反斜杠,以及在执行eval之前使用双引号替换变量$out


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接