I've read the above questions and I still can't work out how to do what I need.

I have a binary command I'll call getreport that does the following:

  1. Prompt for a password (prompt sent to stderr)
  2. Read the password from stdin.
  3. Print extensive data to stdout.

I have another binary command to parse the output from the first command that I'll call processreport. However, it doesn't work with stdin; it will only accept and process a file specified on the command line with a -i flag. It reads from the file, does things with the data it reads in, and outputs data about what it did. (The processreport command can also prompt for a password, entirely separately from getreport.)

I want to use process substitution to make this possible in a single line, rather than requiring a temp file to hold the output of getreport.

Something like:

processreport -i <(getreport)

However, I don't know how to make getreport read in from the terminal the password it requires.

Is this possible?

2 Answers 2

{ getreport | 4<&0 <&3 processreport -i /dev/fd/4; } 3<&0

It could be more simple if you're willing always to read explicitly from /dev/tty:

getreport | 3<&0 </dev/tty processreport -i /dev/fd/3

...or more simply still if you know that stderr will always equal stdin - as it typically does in a terminal...

getreport | 3<&0 <&2 processreport -i /dev/fd/3
  • 3
    That looks too good to be true thus I would like to point out this: "The processreport command can also prompt for a password, entirely separately from getreport." Feb 5, 2016 at 6:35
  • @HaukeLaging - ok, thanks for that - it does complicate matters some, but it doesn't make it much more difficult. i overlooked it i guess, but at least it does explain why processreport requires a named read file.
    – mikeserv
    Feb 5, 2016 at 6:54

getreport cannot read from the terminal because it is a background process.

man 2 read:

EIO : I/O error.
This will happen for example when the process is in a background process group, tries to read from its controlling terminal, and either it is ignoring or blocking SIGTTIN or its process group is orphaned.

I guess what you want is not possible without some shell wrapping. But maybe this is closer to what you want:

mkfifo fifo; read -p "Input for FIFO: " input; echo "$input">fifo &
cat <(read bginput <fifo; echo "$bginput"); rm fifo

This obviously doesn't not work well for wrong passwords and read retries.

mkfifo fifo; read -p "Input for FIFO: " input; echo "$input">fifo &
processreport -i <(getreport <fifo); rm fifo
  • Could you please edit your example to use my made-up commands processreport and getreport? With the way you have it written currently using cat and echo, I can't tell where they're supposed to be dropped in.
    – Wildcard
    Feb 4, 2016 at 20:57
  • @Wildcard Done. Feb 5, 2016 at 4:33
  • why bother using process substitution if you're gonna make a fifo?
    – mikeserv
    Feb 5, 2016 at 6:22

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.