Bash: reading input within while read loop doesn't work

All we need is an easy explanation of the problem, so here it is.

Reading input within a while read loop does not seem to work

while read line
do
 echo "get some input from the user"
 read response
done < some_file.txt

execution does not pause like it would had the read been outside the loop. Why is this? Is there a workaround for reading input within a while read loop?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

The problem is that both read line and read response expects (and gets) data from stdin.
This question on SO explains some of it with a link to even more information.

tl;dr
The accepted answer suggests:

Read from the controlling terminal device: read input </dev/tty

Method 2

let the inner read command use stdin, and use a different file descriptor for the while loop

while read -u 3 line; do
  read -p "get some input from the user" response
done 3< some_file.txt

Method 3

Nifle has it exactly right. When you’re using multiple terminals, however, you need to be specific.

For those of you coming from google, congratulations on finding this page. If you need to do any user input during a while read loop (this includes rm -i, read, or anything else), you can specify which input pipe to use.

Here’s a fragment of this solution that I used:

#in declarations
thistty=$(tty)

lsuser -R LDAP -a home pgrp ALL 2>/dev/null | while read line
do
   homedir=$(echo $homedir | awk -F= '{print $2}')
   sudo rm -ir "$homedir" < $thistty
done

Method 4

Thanks Nifle! And also thanks to bgStack. After searching for hours i finally got the answer! Great one!!
I used “echo $(tty)” to detect my terminal path or you just take it as variable.
For me it was a other use case. U was reading a file and would like to confirm the execution. Maybe the example below helps some one else out.

#!/bin/bash

export terminal=$(tty)

cat file | while read val1 val2
do
   while true; 
            do
              read -p "would you like to XYZ" yn
              case $yn in
                        [Yy]* )     echo "# Move $val1 to $val2        #";break;;
                        [Nn]* )     echo "#---------no action----------#";break;;
                        * )         echo "# Please answer yes or no.   #";;
              esac
            done < $terminal
done

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply