Bash – Wait for key in shell script that may get piped to /bin/bash

bashreadshell-scriptstdin

Consider the following shell script

echo foo; read; echo bar

Running bash my_script outputs 'foo', waits for the return key and outputs 'bar'.

While this works fine running it that way, it doesn't work anymore if piped to /bin/bash:

$ echo 'echo foo;read;echo bar'|bash

directly outputs 'foo' and 'bar' without waiting for a key press.

Why doesn't read work anymore when using it this way?

Is there any way to rewrite the script in a way it works as file script file as well as a script string piped to /bin/bash?

Best Answer

This is really easy, actually, First, you need to set aside your stdin in some remembered descriptor:

exec 9<&0

There. You've made a copy. Now, let's pipe our commands at our shell.

echo 'echo foo; read <&9; echo bar' | bash

...well, that was easy. Of course, we're not really done yet. We should clean up.

exec 9<&-

Ok, now we're done.

But we can avoid the cleanup if we just group our commands a little...

{ echo 'echo foo; read <&9; echo bar' | bash; } 9<&0

The descriptor only survives as long as its assigned compound command does in that case.

Related Question