I am writing a script that should be able to read a number of lines through stdin, so I could use it in pipes such as

Code:

find . -name "*.txt" | myscript

When the script gets input from stdin, it keeps on reading and storing the input until EOF is read, and only then does it start processing the input.All this works perfectly, but now when I want to ask interactive input from the user (Such as "File xxx already exists; do you want to overwrite it? (y/n)") this does not work, since even though the input file or stream was terminated, the input still comes from the stream rather than from the terminal. So instead of waiting for an answer from the user, bash just enters an empty string from the terminated input stream.

Is there any way of telling the shell that from a certain point onwards I want the input to come from the terminal again, even though the user specified another input stream?

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 "doneecho

echo -n "Are you sure you want to print the words you entered? (y/n) "read answer

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...

Who is online

Users browsing this forum: No registered users and 6 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum