How to use Bash read with a timeout?
BashIoTimeoutBash Problem Overview
I can ask the user to press Enter by using read
, and have him wait by calling sleep
. But I can’t think of a way of doing both at the same time. I would like the user to be given the choice:
Press Ctrl+C to Cancel, Enter to continue or just wait 10 seconds
How can I do that?
Bash Solutions
Solution 1 - Bash
In bash
(1), read
has a -t
option where you can specify a timeout. From the manpage:
> read [-ers] [-u fd] [-t timeout] [-a aname] [-p prompt] [-n nchars] [-d delim] [name ...]
>
> -t timeout:
cause read to time out and return failure if a complete line of input is not read within timeout seconds. This option has no effect if read is not reading input from the terminal or a pipe.
Transcript below (without hitting ENTER):
$ date ; read -t 10 -p "Hit ENTER or wait ten seconds" ; echo ; date
Tue Feb 28 22:29:15 WAST 2012
Hit ENTER or wait ten seconds
Tue Feb 28 22:29:25 WAST 2012
Another, hitting ENTER after a couple of seconds:
$ date ; read -t 10 -p "Hit ENTER or wait ten seconds" ; date
Tue Feb 28 22:30:17 WAST 2012
Hit ENTER or wait ten seconds
Tue Feb 28 22:30:19 WAST 2012
And another, hitting CTRL-C:
$ date ; read -t 10 -p "Hit ENTER or wait ten seconds" ; echo ; date
Tue Feb 28 22:30:29 WAST 2012
Hit ENTER or wait ten seconds
(1) If you're doing this in a script, make sure that it's a bash
one. You can do that by adding a shebang line at the start such as one of the following:
#!/usr/bin/env bash
#!/bin/bash
Solution 2 - Bash
The read
builtin has a timeout.
read -t 10
will do it
Solution 3 - Bash
Building on the thoughtful answers above, the return value from the read is useful to distinguish between an empty response from the user (for example "Press Enter" for the default action) and a timeout.
read -t 5 -p "Prompt " RESP
if [[ $? -gt 128 ]] ; then
echo -e "\nTimeout"
else
echo "Response = \"$RESP\"" # adding quotes so empty strings are obvious
fi
Another useful tidbit is that the -p "prompt "
is written to stderr (not stdout) so if you're redirecting stderr, the prompt will not be displayed. An example of this would be logging an execution trace to a log file for later analysis. To use read -p Prompt
in this case you can redirect stderr to the user for just the read statement.
set -x
exec 2>logfile
read -t 5 -p "Prompt " RESP 2>/dev/tty
Solution 4 - Bash
From the bash reference manual :
> read [-ers] [-a aname] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt]
[-t timeout]
[-u fd] [name ...]