JHH
JHH

Reputation: 9285

Bash script running other bash scripts with user input

Let's say I have a bash script which relies on user input (using read and the like).

I now want to run this script N times, each invocation taking an argument, and where those arguments are read from a text file. So essentially I want to do "for each line in text file call script with line as argument and let the user interact with it".

However, when I call my script through my "forall" loop, my read calls are just skipped, no user input is read.

Dumbed down example:

hello.sh:

name=$1
read -p "How old are you, $name? " age

echo "Hello $name, you are $age years old"

This works fine to call as

$ ./hello.sh Adam
How old are you, Adam? <user enters 42>
Hello Adam, you are 42 years old

Now I create my file of names:

names.txt:

Andrew
Benjamin
Charles
David
Edward

And my forall script:

forall.sh:

file=$1
command=$2

while read line; do
    if [ ! -z "$line" ]; then
        $command $line
    fi
done < $file

I now do forall.sh names.txt ./hello.sh, expecting to have my 5 users enter their ages, but instead I get this:

$ forall.sh names.txt ./hello.sh
Hello Andrew, you are Benjamin years old
Hello Charles, you are David years old
Hello Edward, you are  years old

Apparently, the read call will consume a line from the names.txt file instead of reading from a prompt.

How can I do "for each line in file call script with line" and still have the called script accept user input?

Upvotes: 1

Views: 4005

Answers (2)

glenn jackman
glenn jackman

Reputation: 246744

Alternately the while-read loop can use a different file descriptor (not stdin)

# ..............vvv
while read line <&3; do
    [ -n "$line" ] && "$command" "$line"
done 3< "$file"
# ...^^

Upvotes: 1

hek2mgl
hek2mgl

Reputation: 157947

stdin is not the terminal in that loop, it's set to < $file. You need to pass the terminal explicitly to that command as stdin:

while read -r line; do
    if [ ! -z "$line" ]; then
        $command "$line" < /dev/tty
    fi
done < "$file"

Upvotes: 3

Related Questions