7

I have a following small bash script

var=a

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

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 '16 at 6:54
14

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
do
    echo "$var"
    IFS= read -r -t 0.5 -n 1 -s holder && var="$holder"
done

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. – Artak Begnazaryan Dec 11 '14 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 '14 at 16:51
1

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
done

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.