Clear stdin before reading

24,800

Solution 1

I don't think there is a way to clear stdin but (with bash) you can read and discard what is there before you ask for the input

#do some time consuming task here
read -t 1 -n 10000 discard 
read -p "Give me some input: " input

This reads stdin and has a timeout of 1 second, it fails though if there are more than 10000 chars in stdin. I don't know how big you can make the nchars parameter.

Solution 2

In Bash 4, you can set -t (timeout) to 0. In this case, read immediately returns with an exit status indicating whether there's data waiting or not:

# do some time consuming task here
while read -r -t 0; do read -r; done
read -p "Give me some input: " input

Solution 3

function clear_stdin()
(
    old_tty_settings=`stty -g`
    stty -icanon min 0 time 0

    while read none; do :; done 

    stty "$old_tty_settings"
)

clear_stdin

Solution 4

read -d '' -t 0.1 -n 10000

This reads multiple lines of inputs, if the user inadvertently pressed enter multiple times

Solution 5

this worked well for me:

function clean_stdin()
{
    while read -e -t 0.1; do : ; done
}
Share:
24,800

Related videos on Youtube

rabin
Author by

rabin

Updated on September 18, 2022

Comments

  • rabin
    rabin over 1 year

    I have the following bash script:

    # do some time consuming task here
    read -p "Give me some input: " input
    

    Now as you might have guessed, if a user presses some random keys during the "time consuming task", the unwanted input is taken into account as well. How do I clear stdin (or at least ignore it) before I issue the read command?

    • Arcege
      Arcege about 13 years
      Myself, unless you are writing a curses-like program, I find what you wish to do to be a design flaw in your program. UNIX/Linux has the very useful feature of buffering input ("type-ahead") and I commonly make use of this functionality. Coming across your program where you throw away what I typed, I would likely submit a bug and stop using your program until it was fixed.
    • rabin
      rabin about 13 years
      Some users have annoying habit of playing piano with their keyboard while their program is busy doing something. I would rather throw away those keystrokes and start fresh. But you're right, the "type-ahead" is useful, but not always.
  • rabin
    rabin about 13 years
    I actually had found this hack on a forum. I was expecting to find a better way of doing it. Apparently not.
  • user49497
    user49497 about 13 years
    @rabin: If you do find a better way post back here I have it in a few scripts.
  • scai
    scai over 10 years
    Unfortunately this doesn't work with all shells, e.g. dash :(
  • Scott - Слава Україні
    Scott - Слава Україні over 7 years
    I believe that this has nothing to do with the question.
  • Scott - Слава Україні
    Scott - Слава Україні over 7 years
    Using -n is a good idea, but two previous answers have already mentioned it.  And given that the point of this exercise is to read and discard anything that that was typed before the read was executed, I don't understand what good you think the -s is going to do.
  • nhed
    nhed about 7 years
    why -e in this case?
  • pschichtel
    pschichtel about 7 years
    @nhed not sure anymore, maybe to circumvent some system specific problem
  • HiTechHiTouch
    HiTechHiTouch about 7 years
    But it does! The user wants all input discarded. Not allowing input does exactly that -- since stdin is closed, all input is discard (by the system). It's an elegant solution to his problem. He gets the system to do the discard without the trouble of writing a discard loop.
  • Stephen Eilert
    Stephen Eilert about 7 years
    This seems to be the most reliable option so far.
  • Socowi
    Socowi about 5 years
    Seems perfect but does not work for me. I tried bash 5.0.0 and 4.4.19. read will still read the first line entered during # time consuming task. Furthermore, if the script doesn't contain any commands that read stdin after the read then the unread lines are executed on the interactive terminal after the script terminates. Did anyone successfully test this?
  • btalb
    btalb about 4 years
    This only seems to work if the user pressed enter after the keys. If the user has just typed random keys (& no enter press), then the loop exits immediately without clearing the buffered characters.
  • jarno
    jarno about 4 years
    If you leave out word "function", it would work by dash and by any other POSIX compliant shell.
  • Kamil Maciorowski
    Kamil Maciorowski over 3 years
    This is one of very few cases where you shouldn't double-quote a variable. Use stty $old_tty_settings without quotes. The reason is stty -g generates output that is unspecified. Implementations of stty are allowed to generate output with spaces and later expect the shell to split it and pass multiple arguments. What is specified is a constraint that the output of stty -g must be safe when unquoted, it must not trigger word expansion in a shell.
  • kaan_a
    kaan_a almost 3 years
    @KamilMaciorowski I don't get it, is there a downside to the double quotes other than the fact that they aren't necessary?
  • Kamil Maciorowski
    Kamil Maciorowski almost 3 years
    @kaan_a When quoted, the command may not work. It totally depends on the implementation of stty. The specification states the tool should understand its own output (i.e. the output of stty -g) as arguments (plural!) and the output shall not require quoting. If quoted, the string will be a single argument. The specification does not mention "argument" (singular), stty is not required to understand it in this form, it may or may not understand it. Not quoting is the only way that is required to work.
  • Admin
    Admin almost 2 years
    read -n 256 -r -s waits for newline unless you give 256 characters. On the other hand, read -r -t 0 returns 1 unless you press enter.