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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .