I have a following small bash script


while true :
    echo $var
    sleep 0.5
    read -n 1 -s var

It just prints the character entered by the user and waits for the next input. What I want to do is actually not block on the read, i.e. every 0.5 second print the last character entered by the user. When user presses some key then it should continue to print the new key infinitely until the next key press and so on.

Any suggestions?

  • I know is not an answer to the question, but i had a similar issue, where I needed a values coming through STDIN stored in a variable, but read was halting my program and as mentioned if read times out if will empty the content of the variable, my solution was to use parameter expansion, what it does is, if it times out if assigns a "default" value to the variable... var=a while true do echo $var read -t 0.1 input input=${input:-$var} var=$input sleep 0.1 done as I said is not the right answer for you as you just wanted the key pressed and not the value entered... NOTE: whit this timings there
    – maco1717
    Jul 24, 2016 at 6:54

2 Answers 2


From help read:

  -t timeout    time out and return failure if a complete line of input is
        not read within TIMEOUT seconds.  The value of the TMOUT
        variable is the default timeout.  TIMEOUT may be a
        fractional number.  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.  The
        exit status is greater than 128 if the timeout is exceeded

So try:

while true
    echo "$var"
    IFS= read -r -t 0.5 -n 1 -s holder && var="$holder"

The holder variable is used since a variable loses its contents when used with read unless it is readonly (in which case it's not useful anyway), even if read timed out:

$ declare -r a    
$ read -t 0.5 a
bash: a: readonly variable
code 1

I couldn't find any way to prevent this.

  • 1
    What I've tried before was using again the -t option but without holder variable and it was not working. Turns out that read doesn't hold the variable value even if there is no input in the given timeout. Dec 11, 2014 at 16:48
  • @ArtakBegnazaryan Yes, perhaps I should have mentioned that, but I was looking for ways to disable it and lost track.
    – muru
    Dec 11, 2014 at 16:51

A bit late but a (better) solution could be:

while true ; do
    read -r -s -t 0.5; RETVAL=$?
    # ok? echo && continue
    [ $RETVAL -eq 0 ] && echo -E "$REPLY" && continue
    # no timeout ? (EOF or error) break
    [ $RETVAL -gt 128 ] || break

IMHO a bigger timeout won't hurt anybody, as "read" returns as soon as a new line is available...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.