8

Say I've got a bash script:

#!/bin/bash

read -p "Gimme some stuff: " stuff
echo "**${stuff}**"

If the script is invoked with something piping into it, such as:

echo "Here's some stuff" | ./myscript.bash

Then the read command will read from the pipe. Even if I try to clear stdin out before I hit that read command, it will still return immediately.

Is there any way around that? If I don't have any control of the way in which my script is invoked, is there any way to force it to accept input for a read or select from the terminal? If not, are there any sneakier ways to pause the script to get input from a user other than from stdin?

1
  • This is such a wonderfully worded question! It was still very difficult to find because any search matching /bash .* (read|accept|pipe) .* (stdin|tty)/ favors simple questions about how to pipe into a bash script. I'm so glad you managed to break through the algorithm. Jun 25, 2023 at 3:59

1 Answer 1

12

Yes. The terminal is always /dev/tty. All that is necessary is to have read get its input from the terminal rather than stdin:

#!/bin/bash

read -p "Gimme some stuff: " stuff </dev/tty
echo "**${stuff}**"

In operation, this looks like:

$ echo asdfdsaf | read.sh
Gimme some stuff: 123
**123**

A slightly more complex way of doing the same thing

Here we open /dev/tty as file descriptor 3. The option -u 3 tells read to use file descriptor 3:

exec 3<>/dev/tty
read -u 3 -p "Gimme some stuff: " stuff
echo "**${stuff}**"
1
  • /dev/ttty works on Linux. Does it also work on other Unix systems, e.g. macOS?
    – pts
    Apr 28, 2018 at 15:57

You must log in to answer this question.

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