11

I need to listen for any key press in a countdown timer loop. If any key is pressed then the countdown timer should break out of it's loop. This mostly works except for the enter key just makes the countdown timer go faster.

#!/bin/bash
for (( i=30; i>0; i--)); do
    printf "\rStarting script in $i seconds.  Hit any key to continue."
    read -s -n 1 -t 1 key
    if [[ $key ]]
    then
        break
    fi
done
echo "Resume script"

I just can't seem to find any examples of how to detect that enter key anywhere online.

Captain Jimmy
  • 113
  • 1
  • 5

2 Answers2

14

I think based on the return code of read, there is a work around for this problem. From the man page of read,

The return code is zero, unless end-of-file is encountered, read times out,
or an invalid file descriptor is supplied as the argument to -u.

The return code for timeout seems to be 142 [verified in Fedora 16]

So, the script can be modified as,

#!/bin/bash
for (( i=30; i>0; i--)); do
    printf "\rStarting script in $i seconds.  Hit any key to continue."
    read -s -n 1 -t 1 key
    if [ $? -eq 0 ]
    then
        break
    fi
done
echo "Resume script"
devnull
  • 118,548
  • 33
  • 236
  • 227
Sakthi Kumar
  • 3,047
  • 15
  • 28
1

The problem is that read would by default consider a newline as a delimiter.

Set the IFS to null to avoid reading upto the delimiter.

Say:

IFS= read -s -N 1 -t 1 key

instead and you'd get the expected behavior upon hitting the Enter key during the read.

devnull
  • 118,548
  • 33
  • 236
  • 227
  • Unfortunately this caused the same behavior I was getting. The enter key would just continue to the next loop iteration. I was looking at similar solutions to yours but I never found one. – Captain Jimmy Mar 05 '14 at 17:43