1

I want to read repository names from file, show YES-NO-CANCEL dialog and then add the repository if user answers YES. So far, I have written this code:

g_dlg_yes=1
g_dlg_no=0
g_dlg_cancel=127

show_confirm_dlg()
{
    local prompt="$* [y(es)/n(o)/c(ancel)]: "
    local resp=""
    while [ "$resp" != "y" ] && [ "$resp" != "n" ] && [ "$resp" != "c" ]; do
        echo "$prompt"
        read resp
    done
    if [ "$resp" = "y" ]; then
        g_dlg_res=$g_dlg_yes
    elif [ "$resp" = "n" ]; then
        g_dlg_res=$g_dlg_no
    elif [ "$resp" = "c" ]; then
        g_dlg_res=$g_dlg_cancel
    else
        g_dlg_res=$g_dlg_cancel
    fi
}

add_repo()
{
    local filename="/home/stojan/repo.list"
    while read -r line
    do
        local repo_name=$line
        echo "Name read from file - $line"
        show_confirm_dlg "Add repository $repo_name?"
        local rc=$g_dlg_res
        if [ $rc -eq $g_dlg_yes ]; then
            add-apt-repository -y $repo_name
            ##echo $repo_name
        elif [ $rc -eq $g_dlg_no ]; then
            echo "Repository $repo_name rejected"
        elif [ $rc -eq $g_dlg_cancel ]; then
            echo "Script cancelled"
            exit 1
        else
            echo "Unknown response. Now cancelling..."
            exit 1
        fi
        echo "Press ENTER..."
        read _

    done < "$filename"
}

add_repo

The problem is that when I run this script I get stuck at show_confirm_dlg() and get into infinite loop. That is the script doesn't wait for my input and repeats confirmation over and over again.

2 Answers2

4

Using read reads from the standard input. When you use read inside a redirection, it doesn't read from the keyboard, it reads from whatever standard input is at that time.

C.f.:

{
    read a
    echo $a
} < <(echo Hello)

You can duplicate standard input somewhere else to be able to process several streams at the same time:

exec 3<&0          # fd3 now points to the initial stdin
{
    read a         # This reads the "Hello".
    read b <&3     # This reads from the keyboard.
    echo "$a, $b"

} < <(echo Hello)
exec 3<&-          # Close the fd3.
choroba
  • 231,213
  • 25
  • 204
  • 289
0

To get user input from the while...do loop, you can also do:

while [ "$resp" != "y" ] && [ "$resp" != "n" ] && [ "$resp" != "c" ]; do
    echo "$prompt"
    read resp </dev/tty
done

Please refer to this thread: Read input in bash inside a while loop

Community
  • 1
  • 1
Quinn
  • 4,394
  • 2
  • 21
  • 19