How does one code an interactive response in this while loop?
#!/bin/bash
shows=$(< ${HOME}/.get_iplayer/tv.cache)
# ...
# ... stuff with shows omitted ...
# ...
function print_show {
# ...
return
}
while read -r line
do
print_show "$line"
read -n 1 -p "do stuff? [y/n] : " resp # PROBLEM
# ...
# resp actions omitted
# ...
done <<< "$shows"
So a file is read, "processed" then the resulting line oriented data is used in a while read
loop
But the read line within the while loop doesn't work as intended, that is it doesn't wait for the user response, presumably due to the while read
context it is encapsulated by.
Could you please suggest how to fix this or an alternate mechanism?
You've correctly identified that the cause is that within the
while ...; do ...; done <<< "$shows"
loop, stdin has been redirected, thus read
is no longer reading from the keyboard.
You can solve this by using a file descriptor other than 0; for example,
while read -r -u 3 line; do ...; done 3<${HOME}/.get_iplayer/tv.cache
will use FD 3 for the file rather than FD 0, allowing the normal read
(without -u
) to use original stdin, or
while ...; do read -n 1 -p "do stuff? [y/n] : " -u 3 resp; done 3<&0 <<< "$shows"
to clone the original FD 0 to FD 3 before replacing FD 0 with your string.
Since you are already reading the entire file into memory, read it into an array instead of a single string.
# Requires bash 4 or later
mapfile -t loop_input < $HOME/.get_iplayer/tv.cache
for line in "${loop_input[@]}"; do
print_show "$line"
read -n 1 -p "do stuff? [y/n] : " resp
done
If you still use an earlier version of bash, I'd still recommend reading the file into an array instead of a single string, but it's less convenient.
declare -a loop_input
while read; do loop_input+=("$REPLY"); done
for line in "${loop_input[@]}"; do
...
done
or, you can just not read the file all into memory:
while read -u 3 line; do
....
done 3< $HOME/.get_iplayer/tv.cache
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With