Bash script listen for key press to move on

后端 未结 2 407
别那么骄傲
别那么骄傲 2021-02-04 07:26

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.

2条回答
  •  -上瘾入骨i
    2021-02-04 07:32

    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 -r -s -N 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 and 5.0.11, 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 -N 1 && { read -r; break; }
    
    done
    
    # Post-loop command
    date +%s
    

提交回复
热议问题