How to use Bash read with a timeout?

BashIoTimeout

Bash 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 ...]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionqdiiView Question on Stackoverflow
Solution 1 - BashpaxdiabloView Answer on Stackoverflow
Solution 2 - BashJohannes WeissView Answer on Stackoverflow
Solution 3 - Bashuser2070305View Answer on Stackoverflow
Solution 4 - BashBenoitView Answer on Stackoverflow