A: 

You can't. There's no default stdin and redirected stdin. There is stdin, and what it is connected to is either the console, or the file.

The only thing you can do is to do a while using a counter on the number of lines of your file. Then, extract each line using some smart use of sed or tail+head. You cannot use while read line because you would not have any way of differentiating the read from console and the read from the file.

Stefano Borini
Thanks, I was afraid of such. I can probably rewrite it differently, though tail+head is a bit nasty if the file is really big, and sed isn't much better.
Ashton
Then you are using the wrong tool
Stefano Borini
Yes you can - see my answer on /dev/tty.
Colin Macleod
+1  A: 

This should to work:

for LINE in `cat infile`; do
   stuff-done-to-$LINE
   echo "Enter input:"
   read INPUT
   stuff-done-to-$INPUT
done
dimba
+1: yes and no. That will give you a list of words, not a list of lines. You have to change IFS to plain enter for your method to work, which can have dire consequences on the internal code if you are not careful and/or restore it.
Stefano Borini
+2  A: 

I believe this is supported in the Bourne shell:

exec 3<doc.txt
while read LINE <&3
do
    stuff-done-to-$LINE
    # the next two lines could be replaced by: read -p "Enter input: " INPUT
    echo "Enter input:"
    read INPUT
    stuff-done-to-$INPUT
done < infile

Input is alternated between the file and the user. In fact, this would be a neat way to issue a series of prompts from a file.

This redirects the file "infile" to the file descriptor number 3 from which the first read gets its input. File descriptor 0 is stdin, 1 is stdout and 2 is stderr. You can use other FDs along with them.

I've tested this on Bash and Dash (on my system sh is symlinked to dash).

Of course it works. Here's some more fun:

exec 3<doc1.txt
exec 4<doc2.txt
while read line1 <&3 && read line2 <&4
do
    echo "ONE: $line1"
    echo "TWO: $line2"
    line1=($line1) # convert to an array
    line2=($line2)
    echo "Colors: ${line1[0]} and ${line2[0]}"
done

This alternates printing the contents of two files, discarding the extra lines of whichever file is longer.

ONE: Red first line of doc1
TWO: Blue first line of doc2
Colors: Red and Blue
ONE: Green second line of doc1
TWO: Yellow second line of doc2
Colors: Green and Yellow

Doc1 only has two lines. The third line and subsequent lines of doc2 are discarded.

Dennis Williamson
If it works, I learned something new. Thanks.
Stefano Borini
Project and question is long gone, but I went back and checked the relevant shell... yes, it did support file descriptors, so your first example should have worked.The second example with the arrays fails... no arrays in original bourne shell.
Ashton
+2  A: 

You can read/write the user's terminal through /dev/tty, this is independent of what shell you are using and whether stdin/stdout are redirected, so you just need:

echo "Enter input:" > /dev/tty
read INPUT < /dev/tty
Colin Macleod