Read user input inside a loop

Bash

Bash Problem Overview


I am having a bash script which is something like following,

cat filename | while read line
do
    read input;
    echo $input;
done

but this is clearly not giving me the right output as when I do read in the while loop it tries to read from the file filename because of the possible I/O redirection.

Any other way of doing the same?

Bash Solutions


Solution 1 - Bash

Read from the controlling terminal device:

read input </dev/tty

more info: http://compgroups.net/comp.unix.shell/Fixing-stdin-inside-a-redirected-loop

Solution 2 - Bash

You can redirect the regular stdin through unit 3 to keep the get it inside the pipeline:

{ cat notify-finished | while read line; do
    read -u 3 input
    echo "$input"
done; } 3<&0

BTW, if you really are using cat this way, replace it with a redirect and things become even easier:

while read line; do
    read -u 3 input
    echo "$input"
done 3<&0 <notify-finished

Or, you can swap stdin and unit 3 in that version -- read the file with unit 3, and just leave stdin alone:

while read line <&3; do
    # read & use stdin normally inside the loop
    read input
    echo "$input"
done 3<notify-finished

Solution 3 - Bash

Try to change the loop like this:

for line in $(cat filename); do
    read input
    echo $input;
done

Unit test:

for line in $(cat /etc/passwd); do
    read input
    echo $input;
    echo "[$line]"
done

Solution 4 - Bash

I have found this parameter -u with read.

"-u 1" means "read from stdout"

while read -r newline; do
    ((i++))
    read -u 1 -p "Doing $i""th file, called $newline. Write your answer and press Enter!"
    echo "Processing $newline with $REPLY" # united input from two different read commands.
done <<< $(ls)

Solution 5 - Bash

It looks like you read twice, the read inside the while loop is not needed. Also, you don't need to invoke the cat command:

while read input
do
    echo $input
done < filename

Solution 6 - Bash

echo "Enter the Programs you want to run:"
> ${PROGRAM_LIST}
while read PROGRAM_ENTRY
do
   if [ ! -s ${PROGRAM_ENTRY} ]
   then
      echo ${PROGRAM_ENTRY} >> ${PROGRAM_LIST}
   else
      break
   fi
done

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionw2lameView Question on Stackoverflow
Solution 1 - BashdankView Answer on Stackoverflow
Solution 2 - BashGordon DavissonView Answer on Stackoverflow
Solution 3 - BashdimbaView Answer on Stackoverflow
Solution 4 - BashxerostomusView Answer on Stackoverflow
Solution 5 - BashHai VuView Answer on Stackoverflow
Solution 6 - BashMunchk1nView Answer on Stackoverflow