【问题标题】:What is the extra set of () or {} doing to change what gets redirected to /dev/null?额外的一组 () 或 {} 用来改变重定向到 /dev/null 的内容是什么?
【发布时间】:2022-11-29 13:18:05
【问题描述】:

我根据对文件描述符重定向的理解对 bash 进行了一些测试,发现:

((echo STDOUT; echo STDERR >&2;) 3>&1 1>&2 2>&3 3>&-)  2> /dev/null

 (echo STDOUT; echo STDERR >&2;) 3>&1 1>&2 2>&3 3>&-   2> /dev/null

给出了不同的结果。第一个给出 STDERR 的预期输出,因为交换了 stdoutstderr fds,但是第二个给出了 STDOUT 的意外输出,就好像 fds 一开始就没有交换过一样。

这对我来说是令人惊讶的。在这种情况下,我看不到额外的 parenetical 会做什么来改变输出。使用大括号具有相同的效果。

【问题讨论】:

    标签: bash file-descriptor io-redirection


    【解决方案1】:

    重要的是要知道首先处理重定向,即使它们写在命令的末尾也是如此。尽管 2> /dev/null 位于行尾,但它实际上是在子 shell 启动之前执行的。这意味着在第一个示例中它在描述符交换之前执行,但在第二个示例中执行在交换之后。

    让我们深入探讨一下。

    带外子壳

    ((echo STDOUT; echo STDERR >&2;) 3>&1 1>&2 2>&3 3>&-)  2> /dev/null
    

    这相当于:

    2>/dev/null (3>&1 1>&2 2>&3 3>&- (echo STDOUT; >&2 echo STDERR))
    

    步骤是:

    1. 2> /dev/null:fd 2 被重定向到/dev/null
    2. 外部子外壳启动。
    3. 3>&1 1>&2 2>&3 3>&-:fds 1 和 2 被交换了。
    4. 内部子外壳启动。
    5. echo STDOUT:写入fd 1,即/dev/null
    6. >&2:fd 1 被重定向到 fd 2,这是原始 shell 的标准输出。
    7. echo STDERR:写入 fd 2,即标准输出。

      没有外子壳

      (echo STDOUT; echo STDERR >&2;) 3>&1 1>&2 2>&3 3>&-   2> /dev/null
      

      这相当于:

      3>&1 1>&2 2>&3 3>&- 2>/dev/null (echo STDOUT; >&2 echo STDERR))
      

      步骤是:

      1. 3>&1 1>&2 2>&3 3>&-:fds 1 和 2 被交换了。
      2. 2>/dev/null:fd 2 被重定向到/dev/null
      3. 子外壳启动。
      4. echo STDOUT:写入 fd 1,这是原始 shell 的 stderr。
      5. >&2:fd 1被重定向到fd 2,也就是/dev/null
      6. echo STDERR:写入隐藏的 fd 2。

    【讨论】:

      猜你喜欢
      • 2014-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-20
      • 1970-01-01
      • 1970-01-01
      • 2014-10-27
      相关资源
      最近更新 更多