Can someone explain why this command works:

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)

And this fails with "curl: (23) Failed writing body (0 != 4096) (23) Failed writing body" error message:

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)

Redirections to specific file descriptors use 3< file. Process substitution uses <( ... ). To combine the two you need to use both:

3< <( ... )

The space is important — otherwise it's interpreted as an attempted here document that is terminated with (, but that isn't valid and you'll get a parse error.

Your gpg command line needs to be:

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)

This redirects the output of the first curl command into descriptor 3, and the second into descriptor 4, in just the same way as if you read into them from a normal file.

The way that <( ... ) works is that it runs the command with its output connected to either a FIFO or an entry under /dev/fd, and then <( ... ) gets replaced in the command line with the path to that file as an ordinary argument, just as though it'd been written there in the first place. The file path can then be used with other constructs, like redirection.

Your original command ends up running gpg ... 3/dev/fd/63 4/dev/fd/64, and then curl finds that nobody is interested in what it's writing and reports that error. I also got an error from gpg itself saying that those files don't exist, although it was buried in the curl output.

  • Michael, do you know if the minus in -&3 is gpg-specific? If it's in POSIX, I'm unable to track it down in the documentation – iruvar Mar 11 '16 at 17:00
  • 2
    @1_CR That's a gpg thing, activated by --enable-special-filenames. – Gilles 'SO- stop being evil' Mar 11 '16 at 20:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.