Shell Script – How to Read User Input from a Pipe

pipeshellshell-scriptuser input

Let's assume I have a file named confirmation.sh with the following content:

#!/bin/bash
echo -n "Are you sure [Y/n]? "
read line
case "$line" in
    n|N) echo "smth"
        ;;
    y|Y) echo "smth"
        ;;
esac

and I want to run this script in the following way:

cat confirmation.sh | sh

I see Are you sure [Y/n]? and the script is interrupted. What's the problem?

Best Answer

As others have said, this is because the stdin of sh has been redirected to read from the pipe, it is not connected to the terminal as it would normally be. One thing you can do to get around this is to use /dev/tty to force the script to read from the terminal. Eg:

#!/bin/sh

read -p "Are you sure [Y/n]?" line </dev/tty
case "$line" in
  y|Y) echo "confirmed"
    ;;
  *) echo "not confirmed"
    ;;
esac

Normally you would only do this if you specifically want to prevent people from scripting the input, eg:

echo Y | sh confirmation.sh

This would still read from the terminal even though the user might expect this to automatically input Y at the prompt. It is common for programs that expect a password to do this.

Related Question