2

This is my script to detect keys pressed:

#!/bin/bash
echo "Reading keys."
while [ "x$keypress" = "x" ]; do
  read -n 1 -t 1 -s keypress
  printf "."
done
printf "\n"
echo "Pressed key: "$keypress

That seems to work OK (example pressing the "q" key after a while):

$ ./InputKey.sh
Reading keys.
.............................................
Pressed key: q

But if I put it inside a loop that reads my File.txt and waits for a key for each line:

#!/bin/bash
MyList=File.txt
while IFS=, read -ra ListLine
do
    echo "Processing line: "$ListLine
    echo "Press [S] to count as Secret or [P] to count as Public."
  while [ "x$keypress" = "x" ]; do
        read -n 1 -t 1 -s keypress
    printf "."
    done
    printf "\n"
    echo "Pressed key: "$keypress
done < "$MyList"

The program does not wait for keypressing at all, and this is the weird result:

$ ./prueba07.sh
Processing line: d:\Temp
Press [S] to count as Secret or [P] to count as Public.
.
Pressed key: c
Processing line: :\Temp
Press [S] to count as Secret or [P] to count as Public.

Pressed key: c
Processing line: e:\Temp
Press [S] to count as Secret or [P] to count as Public.

Pressed key: c
Processing line:
Press [S] to count as Secret or [P] to count as Public.

Pressed key: c

And this is the File.txt content:

d:\Temp
c:\Temp
e:\Temp 

I have read somewhere that the problems comes from the <"$MyList" redirector, that consumes all the stdin.

So, I have found this thread and added &3 redirector:

#!/bin/bash
MyList=File.txt
while IFS=, read -ra ListLine <&3
do
    echo "Processing line: "$ListLine
    echo "Press [S] to count as Secret or [P] to count as Public."
  while [ "x$keypress" = "x" ]; do
        read -n 1 -t 1 -s keypress
    printf "."
    done
    printf "\n"
    echo "Pressed key: "$keypress
done 3< "$MyList"

Now the program wait for one key pressing. But the rest is automatically repeated (example when pressing p only once):

$ ./prueba07.sh
Processing line: d:\Temp
Press [S] to count as Secret or [P] to count as Public.
..
Pressed key: p
Processing line: c:\Temp
Press [S] to count as Secret or [P] to count as Public.

Pressed key: p
Processing line: e:\Temp
Press [S] to count as Secret or [P] to count as Public.

Pressed key: p
Processing line:
Press [S] to count as Secret or [P] to count as Public.

Pressed key: p

How can be such problem solved? Thanks you.

EDIT-01: Tested this change for the read key line with no results:

read -n 1 -t 1 -s keypress </dev/tty

extracted from this other thread.

EDIT-02: Tested on Ubuntu Desktop v12 and CygWin (Windows 7).

EDIT-03: Answers below are correct. The final change that I have choosen for my script has been (just one line at the end):

#!/bin/bash
MyList=File.txt
while IFS=, read -ra ListLine <&3
do
    echo "Processing line: "$ListLine
    echo "Press [S] to count as Secret or [P] to count as Public."
  while [ "x$keypress" = "x" ]; do
        read -n 1 -t 1 -s keypress
    printf "."
    done
    printf "\n"
    echo "Pressed key: "$keypress
    unset keypress
done 3< "$MyList"
Community
  • 1
  • 1
Sopalajo de Arrierez
  • 3,543
  • 4
  • 34
  • 52

2 Answers2

2

You can read from a different file descriptor, and refactor the inner loop

while IFS=, read -r -u 3 -a ListLine
do
  echo 'Processing line:' "$ListLine"
  echo 'Press [S] to count as Secret or [P] to count as Public.'
  until read -n 1 -t 1 -s keypress
  do
    printf .
  done
  echo
  echo 'Pressed key:' $keypress
done 3< File.txt

Does bash support doing a read nested within a read loop?

Community
  • 1
  • 1
Zombo
  • 1
  • 62
  • 391
  • 407
  • Your script seems to have minor modifications, but I think it is correct. Lets note that `while IFS=, read -r -u 3 -a ListLine` and `while IFS=, read -ra ListLine <&3` are equivalent. – Sopalajo de Arrierez Dec 08 '14 at 03:02
1

It works after the first loop because keypress was empty but on the subsequent calls, keypress is still set to the value was set during the first time through the loop. You just need to set keypress variable to an empty string.

Claudio Corsi
  • 329
  • 1
  • 4
  • Mmm.. I am testing it, and it seems you are right, Claudio. Thanks you. You should edit your answer to enhance it in order to fit the forum rules. At least, I think you must add an example (just a simple mod of my script would be enough). Thanks you. – Sopalajo de Arrierez Dec 08 '14 at 02:48