bash: non blocking read inside a loop
14,674
Solution 1
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.
Solution 2
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...
Related videos on Youtube
Author by
Artak Begnazaryan
Updated on September 18, 2022Comments
-
Artak Begnazaryan over 1 year
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?
-
Andra almost 8 yearsI 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
-
-
Artak Begnazaryan over 9 yearsWhat I've tried before was using again the
-t
option but withoutholder
variable and it was not working. Turns out thatread
doesn't hold the variable value even if there is no input in the given timeout. -
muru over 9 years@ArtakBegnazaryan Yes, perhaps I should have mentioned that, but I was looking for ways to disable it and lost track.