Bash can run scripts from pipeline. A minimal example would be:

> echo "echo hello world" | bash
hello world

This is handy if you wants to run a script downloaded from curl or wget.

But apparently, you cannot use read in this kind of script execution. For example,


echo 'input: '
read HELLO
echo hello: $HELLO

If you simply run the above script from a bash script file, you'd get to input the value of $HELLO. and the echo hello: $HELLO will print the result.

If you feed the script in the manner we talked about previously:

> echo "echo 'input: '; read HELLO; echo hello: $HELLO" | bash

You won't get the interaction at all. And $HELLO remains empty. I've also tried to add -i option in bash, and it didn't work.

Is there any way we can use read in the pipelined script? How? Or, if we can't, why?


1 Answer 1


read will "interact" with the user via the stdin (where it will read stuff from) and stderr (where it will print its -p prompt, if any).

If the stdin is the script, read will get its stuff from it, causing it to skip a line:

$ echo '
read foo
what the -)(*$;?
echo "$foo"
' | bash
what the -)(*$;?

This is hardly a good practice, and will not work in all shells. Also notice that when piping scripts via stdin, bash will have to read them byte-by-byte.

In your example, your whole script was a single line, so the read builtin will just get EOF and not set any variables.

If you want read to always read from the controlling tty, then redirect it explicitly:

read var </dev/tty

This should be used sparingly, too. Nobody will appreciate you if they have to use expect(1) in order to instrument your script.

You must log in to answer this question.

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