Reputation: 3558
I want to get the user input in a bash script that is first downloaded via wget (proxied in the examble below using cat) and then fed into bash through stdin. I thought it would be straightforward but it doesn't work.
The script (in a file called gistfile2.sh):
#!/bin/bash
echo -n "Enter path: "
read path
echo $path
How I run it:
root@precise32:/tmp# cat (or wget -qO-) gistfile2.sh | bash
Enter path: root@precise32:/tmp#
Any ideas?
Upvotes: 0
Views: 64
Reputation: 295815
First, let's look at how pipelines work:
When
foo | bar
runs bar
, bar's stdin is connected to foo
's stdout. This means that bar
has no way of knowing what stdin descriptor it would have inherited were it not for the pipeline overriding it. This information is lost, and cannot be recovered.
However, in practice, one can often guess: If stderr
is still a TTY handle, that can be opened for stdin; and if the operating system provides a facility such as /dev/tty
to get a handle on the process's controlling tty, all the better.
So:
If your stdin (FD 0) has been overridden by a pipeline, you can try to read from /dev/tty
. This is not by any means guaranteed to work, and is heavily platform-dependent functionality -- but if it doesn't work, then you'll be falling back on other hackery such as hoping that stderr hasn't been redirected.
To read from /dev/tty
:
read path </dev/tty || { rc=$?; echo "Unable to read from TTY" >&2; exit "$rc"; }
To read from stderr (assuming that it's connected to a read/write FD going to your TTY -- a big assumption):
read path <&2 || { rc=$?; echo "stderr not attached to a TTY?" >&2; exit "$rc"; }
Upvotes: 2