Cat file to terminal at particular speed of lines per second
Short and readable:
perl -pe "system 'sleep .003'" log.txt
I post this solutions because they are small and readable, as comments of DMas's answer seem promote this kind of solution!
But I hate this because: For this run, perl will fork to /bin/sleep
300x / seconds!
This is a big ressource consumer! Also a wrong good solutions!!
Using builtin sleep in perl
Unfortunely, builtin sleep
is limited to integers. So we have to use select
instead:
perl -e 'print && select undef,undef,undef,.00333 while <>;'
Under perl, print while <>
could be replaced by the -p
switch:
perl -pe 'select undef,undef,undef,.00333'
Let's try:
time /bin/ls -l /usr/bin | perl -pe 'select undef,undef,undef,.00333' | wc
2667 24902 171131
real 0m9.173s
user 0m0.056s
sys 0m0.048s
bc -l < <(echo 2667/9.173)
290.74457647443584432573
Explanation:
300 lines / sec means 1 line by 0.0033333333 secs.
print
without argument prints$_
which is default input space.called as
... | perl -e
,... | perl -ne
or... | perl -pe
, standard input would be automaticaly assigned to*STDIN
which is default file descriptor, so<>
would do the same as<STDIN>
which will read from standard input until$/
(input record separator which is by default a newline) will be reached. In English, by default<>
will read one line from standard input and assign content to$_
variable.&&
is an and condition, but is used there as a chain command separator so after (successfully) print one line, doing next command.select
is a programmer's trick to not usesleep
. This command is designed to trap events on file descriptors (inputs and/or outputs, files, socket and/or net sockets). With this command, a program could wait for 3 kind of events, feed ready to read, feed ready to write and some event happened on feed. The fourth argument is a timeout in seconds, so syntax isselect <feeds where wait for input>, <feeds where having to write>, <feed where something could happen>, <timeout>
.
For more precision, you could use Time::Hires
perl module:
perl -MTime::HiRes -pe 'BEGIN{$start=Time::HiRes::time;$sleepPerLine=1/300};select undef,undef,undef,($start + $sleepPerLine*$. - Time::HiRes::time)'
Note: $.
is current input line number.
Better written as cat >catLps.pl
#!/usr/bin/perl -w
use strict;
use Time::HiRes qw|time|;
my $start=time;
my $lps=300;
$lps=shift @ARGV if @ARGV && $ARGV[0]=~/^(\d+)$/;
my $sleepPerLine=1/$lps;
print &&
select undef,undef,undef,($start + $sleepPerLine*$. - Time::HiRes::time)
while <>
Usage:
catLps.pl [lps] [file] [file]...
First argument
lps
is optional line per seconds numeric argument (default: 300)Note: if filename is only numeric, you may have to specifiy them with path:
./3
.Like
cat
this could pass files given as argument and/or standard input
So we could:
TIMEFORMAT='%R'
time seq 1 100 | ./catLps.pl 100 >/dev/null
1.040
time seq 1 10000 | ./catLps.pl 10000 >/dev/null
1.042
For fun:
export TIMEFORMAT='%R' ;clear ;time seq 1 $((LINES-2)) | ./catLps.pl $((LINES-2))
just use awk with sleep:
awk '{print $0; system("sleep .1");}' log.txt