Bash script listen for key press to move on

2019-03-15 02:35发布

问题:

So, I want to write a bash script that are a sequence of steps and ill identify it as "task#". However, each step is only completed and can run as long as the user wants.

Do task1
if keypressed stop task1 and move on #this is the part I need help with. There can be up to 10 of these move on steps. 
Do task2
...

kina like top; it keeps doing stuff until you hit q to quite, however, i want to move on to the next thing

回答1:

you can use read builtin command with option -t and -n

while :
do
    # TASK 1
    date
    read -t 1 -n 1 key

    if [[ $key = q ]]
    then
        break
    fi
done

# TASK 2
date +%s


回答2:

kev's great solution works well even in Bash 3.x., but it introduces a 1-second delay (-t 1) in every loop iteration.

In Bash 3.x, the lowest supported value for -t (timeout) is 1 (second), unfortunately.

Bash 4.x supports 0 and fractional values, however:

A solution that supports an arbitrary key such as q requires a nonzero -t value, but you can specify a value very close to 0 to minimize the delay:

#!/bin/bash
# !! BASH 4.x+ ONLY

while :; do

  # Loop command
  date

  # Check for 'q' keypress *waiting very briefly*  and exit the loop, if found.
  read -t 0.01 -rN 1 && [[ $REPLY == 'q' ]] && break

done

# Post-loop command
date +%s

Caveat: The above uses 0.01 as the almost-no-timeout value, but, depending on your host platform, terminal program and possibly CPU speed/configuration, a larger value may be required / a smaller value may be supported. If the value is too small, you'll see intermittent error setting terminal attributes: Interrupted system call errors - if anyone knows why, do tell us.


Tip of the hat to jarno for his help with the following:

Using -t 0, works as follows, according to help read (emphasis added):

If TIMEOUT is 0, read returns immediately, without trying to read any data, returning success only if input is available on the specified file descriptor.

As of Bash v4.4.12, unfortunately, -t 0 seems to ignore -n / -N, so that only an ENTER keypress (or a sequence of keypresses ending in ENTER) causes read to indicate that data is available.
If anyone knows whether this is a bug or whether there's a good reason for this behavior, do let us know.

Therefore, only with ENTER as the quit key is a -t 0 solution currently possible:

#!/bin/bash
# !! BASH 4.x+ ONLY

while :; do

  # Loop command
  date

  # Check for ENTER keypress and, after clearing the input buffer
  # with a dummy `read`, exit the loop.
  read -t 0 -r && { read -r; break; }

done

# Post-loop command
date +%s


标签: bash shell