1

I'm familiar with process substitution used the canonical way, e.g.

diff <(ls /folder1) <(ls /folder2)

However, can it be used when the process asks for an argument that is not just the path to the expression? E.g.

curl -XPOST https://host:1234/upload -F data=@$(echo <(head -c1M /dev/urandom))

This doesn't work because the inner substitution exists for the subshell process, not the outer process; nonetheless, it is effectively what I'm trying to achieve.

  • 2
    Isn't data=@<(head -c1M /dev/urandom) what you want? (And btw this example wouldn't work because you can't have null bytes in a command argument.) – Gilles Jul 20 '16 at 22:00
  • @Gilles Ah, I'd used quotes when I tested. Didn't realize <() is parseable mid-string as long as it's not quoted. Thanks! (also, if you post your response as an answer, will mark it) – user508633 Jul 20 '16 at 23:56
  • @Gilles <() returns a path to a file descriptor, not the data in the pipe, so there wouldn't actually be any NULs in the arguments. – Dylan Frese Jul 22 '16 at 21:32
2

When you use the <(cmd) syntax what typically happens is the "cmd" is run with stdout connected to a temporary file descriptor, and the file name of that descriptor returned, so it can be used as a parameter

e.g

ksh$ echo <(echo hello)
/dev/fd/4

bash$ echo <(echo hello)
/dev/fd/63

Now that /dev/fd/## entry is only valid in scope for the shell that is calling <(..) because /dev/fd is a symlink to /dev/self/fd.

This means that in your example of data=@$(echo <(head -c1M /dev/urandom)) if will be parsed as if you'd entered data=@/dev/fd/63 but that won't work because the shell that is running the curl command isn't the shell that had the process subsitution.

Now <(...) can be included inside other entries and it will work, as long as you don't pass the temporary filenames around

eg this won't work

$ cat <(echo <(echo hello))
/dev/fd/63

but this will work

$ cat <(cat <(echo hello))
hello

In your version, though, you have an unnecessary level of indirection and should be able to simply do

data=@<(head -c1M /dev/urandom)
  • Yup, this is basically what I gathered as well. What I was missing here was that <() inside a string works, with the exception of quotes. This is a good overview of the situation, however, so I will accept this. Thanks for the response! – user508633 Jul 23 '16 at 2:30

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.