Search code examples
pipeshposix

Interactive shell using standard input


I'd like to launch a shellscript which has interactive parts inside via pipe.

For example,

cat hoge.sh | sh

and hoge.sh

#!/bin/sh
read yn
echo "yn is $yn"

In this case, sh hoge.sh works but cat hoge.sh | sh not.

Which option should I put ? or is it impossible? hopefully, I make a script which follows POSIX.


Solution

  • Method 1: Get user input via stderr

    The problem is stdin for the shell is the cat process and, apparently, you would like the question the user. One way to do that is:

    $ cat hoge.sh
    #!/bin/sh
    read yn <&2
    echo "yn is $yn"
    

    This tells read to get its stdin from the stderr, not the cat process. Since stderr has not been redirected, it is still the terminal

    In operation, it looks like this:

    $ cat hoge.sh | sh
    y
    yn is y
    

    Method 2: Get user input directly from the terminal

    $ cat hoge.sh
    #!/bin/sh
    read yn </dev/tty
    echo "yn is $yn"
    

    When done this way, the read command will get its input from the terminal and any attempt at I/O redirection will be ignored. This can be an advantage or disadvantage depending on your requirements.