bash 中的文件描述符和重定向

kay*_*kay 4 bash io-redirection file-descriptors process-substitution

有人可以解释为什么这个命令有效:

gpg --enable-special-filenames --verify --batch \
  <(curl -s https://www.gnupg.org/ftp/gcrypt/gnupg/gnupg-2.0.29.tar.bz2.sig) \
  <(curl https://www.gnupg.org/ftp/gcrypt/gnupg/gnupg-2.0.29.tar.bz2)
Run Code Online (Sandbox Code Playgroud)

这失败了“卷曲:(23)写入正文失败(0!= 4096)(23)写入正文失败”错误消息:

gpg --enable-special-filenames --verify --batch -- '-&3' '-&4' \
  3<(curl -s https://www.gnupg.org/ftp/gcrypt/gnupg/gnupg-2.0.29.tar.bz2.sig) \
  4<(curl https://www.gnupg.org/ftp/gcrypt/gnupg/gnupg-2.0.29.tar.bz2)
Run Code Online (Sandbox Code Playgroud)

Mic*_*mer 5

重定向到特定文件描述符使用3< file. 进程替换使用<( ... ). 要将两者结合起来,您需要同时使用两者

3< <( ... )
Run Code Online (Sandbox Code Playgroud)

空格很重要 - 否则它会被解释为一个以 结尾的尝试的here 文档(,但这不是有效的,你会得到一个解析错误。


您的gpg命令行必须是:

gpg --enable-special-filenames --verify --batch -- '-&3' '-&4' \
    3< <(curl -s https://www.gnupg.org/ftp/gcrypt/gnupg/gnupg-2.0.29.tar.bz2.sig) \
    4< <(curl https://www.gnupg.org/ftp/gcrypt/gnupg/gnupg-2.0.29.tar.bz2)
Run Code Online (Sandbox Code Playgroud)

这将第一个curl命令的输出重定向到描述符 3,第二个命令的输出重定向到描述符 4,就像从普通文件中读取它们一样。


该方法<( ... ) 的工作原理是,它运行具有其输出端连接到任何一个FIFO或下一个条目的命令/dev/fd,然后<( ... )在与路径,文件作为普通参数的命令行被替换,就好像它会被写入首先是那里。然后可以将文件路径与其他结构一起使用,例如重定向。

您的原始命令最终运行gpg ... 3/dev/fd/63 4/dev/fd/64,然后curl发现没有人对其所写的内容感兴趣并报告该错误。我自己也收到了一个错误,gpg说这些文件不存在,尽管它被隐藏在curl输出中。

  • @1_CR 那是 gpg 的东西,由`--enable-special-filenames` 激活。 (2认同)