How to print text in the terminal as if it's being typed?
This does not work with Wayland; if you're using Ubuntu 17.10 and didn't change to using Xorg at login, this solution isn't for you.
You can use xdotool
for that. If the delay between the keystrokes should be consistent, it's as simple as that:
xdotool type --delay 100 something
This types something
with a delay of 100
milliseconds between each keystroke.
If the delay between the keystrokes should be random, let's say from 100 to 300 milliseconds, things get a bit more complicated:
$ text="some text"
for ((i=0;i<${#text};i++));
do
if [[ "${text:i:1}" == " " ]];
then
echo -n "key space";
else
echo -n "key ${text:i:1}";
fi;
[[ $i < $((${#text}-1)) ]] && echo -n " sleep 0.$(((RANDOM%3)+1)) ";
done | xdotool -
This for
loop goes through every single letter of the string saved in variable text
, printing either key <letter>
or key space
in the case of a space followed by sleep 0.
and a random number between 1 and 3 (xdotool
's sleep
interprets the number as seconds). The whole output of the loop is then piped to xdotool
, which prints the letters with the random delay in between. If you want to change the delay just change the (RANDOM%x)+y
part, y
being the lower and x-1+y
the upper limit – for 0.2 to 0.5 seconds it would be (RANDOM%4)+2
.
Note that this approach does not print the text, but rather type it exactly like the user would do, synthesizing single keypresses. In consequence the text gets typed into the currently focused window; if you change the focus part of the text will get typed in the newly focused window, which may or may not be what you want. In either case have a look at the other answers here, all of which are brilliant!
I tried xdotool after reading @dessert's answer but couldn't get it to work for some reason. So I came up with this:
while read line
do
grep -o . <<<$line | while read a
do
sleep 0.1
echo -n "${a:- }"
done
echo
done
Pipe your text into the above code and it will be printed like typed. You can also add randomness by replacing sleep 0.1
with sleep 0.$((RANDOM%3))
.
Extended version with fake typos
This version will introduce a fake typo every now and then and correct it:
while read line
do
# split single characters into lines
grep -o . <<<$line | while read a
do
# short random delay between keystrokes
sleep 0.$((RANDOM%3))
# make fake typo every 30th keystroke
if [[ $((RANDOM%30)) == 1 ]]
then
# print random character between a-z
printf "\\$(printf %o "$((RANDOM%26+97))")"
# wait a bit and delete it again
sleep 0.5; echo -ne '\b'; sleep 0.2
fi
# output a space, or $a if it is not null
echo -n "${a:- }"
done
echo
done
You mention a consistent delay between characters, but if you really want it to look like its being typed, the timing won't be perfectly consistent. To achieve this you can record your own typing with the script
command and play it back with scriptreplay
:
$ script -t -c "sed d" script.out 2> script.timing
Script started, file is script.out
Wake up ...
Wake up ...
Wake up Neo ...
Script done, file is script.out
$
$ scriptreplay script.timing script.out
Wake up ...
Wake up ...
Wake up Neo ...
$
Recording is stopped by hitting CTRL-D.
Passing the -t
parameter to script
instructs it also generate timing information, which I have redirected to the script.timing
file. I have passed sed d
as a command to script
as this is simply a way to absorb input (and this record the keystrokes) with no side-effects.
If you want to do all the tput
/reset
stuff too, you might want to do a script
recording for each of your lines, and play them back, interleaved with the tput
/reset
commands.