Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It's 100% free, no registration required.

I was doing something like the following minimal example:

#! /bin/sh

# $1 = file containing list of files to sync
# $2 = source dir ; $3 = target dir

cat "$1" | while read f
do
    cp -i "$2"/"$f" "$3"/"$f"
done

I find that cp -i doesn't wait for my input at all and the loop just runs to the end. Why, and what can be done to fix the situation?

share|improve this question

1 Answer 1

Digging around here, I understood from http://unix.stackexchange.com/a/56877/54067 (where both the question and answer are worded differently and the problem is not related to interactive input) that the reason for the problem is that the cp -i expects the user to give the interactive input confirmation via stdin but in the cat | while read loop stdin is busy with the pipe and so the following line(s) from the input file is/are chewed up as user input.

So the solution is also similar to that advised at the other question -- to pipe the content through a different file descriptor than stdin:

while read f <&3
do
    cp -i "$2"/"$f" "$3"/"$f"
done 3< "$1"

Note the <&3 and 3< "$1" at the top and bottom of the loop.

Thanks to @StéphaneChazelas for the answer in the other q. (I upvoted it.)

Further, posting this here obviously I'd like to know if there are any other solutions for interactive input other than this.

Also note that while using a for loop is a possible as in the other q, I'm worrying that the $(cat "$1") in for f in "$(cat "$1")" will use up unnecessary memory by expanding the file in place if it is a very big one. OTOH the pipe should handle reading line by line IIUC. So I don't think using for is an efficient solution. I'd like comments on this as well.

share|improve this answer
    
See also unix.stackexchange.com/a/87303 –  Stéphane Chazelas Nov 27 '14 at 15:48
2  
You can also use cp ... < /dev/tty for cp's stdin to be the controlling terminal if any whatever the original (outer) stdin is currently refering to. –  Stéphane Chazelas Nov 27 '14 at 15:50
2  
@StéphaneChazelas And then the user of your script will doubly curse you, once for using cp -i and one for making him use expect instead of yes |. –  Gilles Nov 27 '14 at 22:41

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.