This thread on nonblocking I/O in bash might help.
It suggests using stty
and dd
.
Or you could use the bash
read
builtin with the -t 0
option.
# do your stuff
# discard rest of input before exiting
while read -t 0 notused; do
read input
echo "ignoring $input"
done
If you only want to do it if the user is at a terminal, try this:
# if we are at a terminal, discard rest of input before exiting
if test -t 0; then
while read -t 0 notused; do
read input
echo "ignoring $input"
done
fi
sh
(as in the sh
language specification) doesn't come with a line editor. Terminal drivers have a rudimentary line editor that allow for backspace and a few other keys to edit the entered line, but generally not arrow keys.
You can insert a default value into the terminal driver input buffer using the TIOCSTI
ioctl like:
printf 'Please enter the value: '
value=the-default
perl -MPOSIX -e 'require "sys/ioctl.ph"; tcflush 0,2;
ioctl(STDIN, &TIOCSTI, $_) or die "$!\n"
for split "", join " ", @ARGV' "$value"
IFS= read -r value
Upon the read
, the content of $value
(the-default
) will have been inserted as if typed.
Now, if you want a more advanced line editor like provided by libreadline
where you can use arrow keys, you can use things like rlwrap
(not a standard command though):
value=the-default
value=$(rlwrap -S 'Please enter the value: ' -P "$value" -o cat)
rlwrap
is typically used to add a readline
-like line editors to applications that don't have one. Above we're adding a line editor to cat
, and using it in one-shot mode (-o
), so that cat
returns after one line is entered (though you can still enter more than one line with Ctrl+V, Ctrl-J like in bash
.
If you're ready to use non-standard shells, zsh
or bash
have builtins for that using their own line editor.
In zsh
:
value=the-default
vared -p 'Please enter the value: ' value
In bash
:
value=the-default
IFS= read -re -i "$value" -p 'Please enter the value: ' value
Best Answer
With
zsh
, you can useprint -z
to place some text into the line editor buffer for the next prompt:would prime the line editor with
echo test
which you can edit at the next prompt.I don't think
bash
has a similar feature, however on many systems, you can prime the terminal device input buffer with theTIOCSTI
ioctl()
:Would insert
echo test
into the terminal device input buffer, as if received from the terminal.A more portable variation on @mike's
Terminology
approach and that doesn't sacrifice security would be to send the terminal emulator a fairly standardquery status report
escape sequence:<ESC>[5n
which terminals invariably reply (so as input) as<ESC>[0n
and bind that to the string you want to insert:If within GNU
screen
, you can also do:Now, except for the TIOCSTI ioctl approach, we're asking the terminal emulator to send us some string as if typed. If that string comes before
readline
(bash
's line editor) has disabled terminal local echo, then that string will be displayed not at the shell prompt, messing up the display slightly.To work around that, you could either delay the sending of the request to the terminal slightly to make sure the response arrives when the echo has been disabled by readline.
(here assuming your
sleep
supports sub-second resolution).Ideally you'd want to do something like:
However
bash
(contrary tozsh
) doesn't have support for such await-until-the-response-arrives
that doesn't read the response.However it has a
has-the-response-arrived-yet
feature withread -t0
:Further reading
See @starfry's answer's that expands on the two solutions given by @mikeserv and myself with a few more detailed information.