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
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
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