Hi jeo!
Actually I haven't found an answer yet...
I'm not sure if I fully understand what you mean, but I'll try to be a bit clearer about what I mean:
I won't bother to explain what exactly 'myscript' does since it's a rather long explanation and it doesn't really matter. The important thing is that it normally takes a number of filenames as arguments and then does stuff with these files, e.g. creating symbolic links to them.
So a call
Code:
myscript file1 file2 file3
would process the 3 files given and create links to them. However, under certain circumstances, the script will prompt the user whether or not to create a directory (in which the links will be created). So the script could ask a question like "Directory /foo/bar does not exist. Do you want to create it?" and then wait for input from the user, which it obviously reads from stdin. So far everything works fine.
Now I also want to be able to read filenames (not the files themselves) from the input stream instead of getting them as arguments, in order to create pipes like
Code:
find . -name "*.txt" | myscript
So if the result of "find . -name "*.txt"" are the files foo.txt and bar.txt, then the above call should be equivalent to
Code:
myscript foo.txt bar.txt
(I know that in this specific case I could also have writen "myscript *.txt", but you can imagine one would want to do more complex queries using find.)
The script (called 'myscript' here) succesfully reads the filenames from stdin using a while read loop. So it keeps on reading from the input stream until an EOF character is read and treats every line as a filename. The problem is that now I can't ask input from the user anymore, since the input stream now comes from the pipe and not from the terminal. So now, when the script asks "Do you want to create directory /foo/bar?", the user can't answer anymore, since the script is not reading from the terminal, but from the pipe, which is finished since an EOF was read before.
So my question is: How (if at all) can I tell a script to read from the terminal, even though it is used in a pipe? Or formulated another way: How can I first read input from a pipe until I reach the end of the pipe (an EOF), and then redirect the input stream to come from the terminal?
The while read loop you suggest would call 'myscript' for each output line of 'find' separately. This is not really what I want, and I don't think it solves the problem: if 'myscript' needs interactive input to process the information coming from the pipe, it still needs a way to get its input from the terminal again.
The following (stupid) script shows the problem:
Code:
#!/bin/bash
words=""
while read -p"> " line; do
words="$words$line "
done
echo
echo -n "Are you sure you want to print the words you entered? (y/n) "
read answer
if [[ $answer != 'n' ]]; then
echo "The words you entered are:"
echo "$words"
fi
exit
If you run it from a terminal, everything works fine: you can keep entering words until you press Ctrl-D (which is EOF), then it asks you if you want to print the words, and unless you answer "n", the words are printed.
But if you call it using a pipe, e.g.
Code:
(echo "These"; echo "are"; echo "words") | myscript
where 'myscript' is the above script, the output is
Code:
Are you sure you want to print the words you entered? (y/n) The words you entered are:
These are words
You see that the words are still read correctly, but the script will print them without waiting for your answer. This is the problem I want to solve...
Thanks for your help!
Pieter