You are not logged in.

#1 2021-03-26 19:09:46

Colonel Panic
Member
Registered: 2018-11-13
Posts: 370

Countdown timer in a terminal

Hi everybody,

I know that some people here write or use bash scripts, and there's recently been a thread about alarm clock scripts.

https://forums.bunsenlabs.org/viewtopic.php?id=6257

Here's something similar; I've been looking for a way to have a simple, unobtrusive countdown timer, and came across this script (which works in a terminal and counts down 20 seconds at a time);

seconds=20; date1=$((`date +%s` + $seconds));
while [ "$date1" -ge `date +%s` ]; do
  echo -ne "$(date -u --date @$(($date1 - `date +%s` )) +%H:%M:%S)\r";
done

I'm using it now and can testify that it works.

Here's a thread with some more and similar ideas in it;

https://superuser.com/questions/611538/ … a-terminal

Last edited by Colonel Panic (2021-03-26 19:11:15)

Offline

#2 2021-04-07 10:41:30

Obadobo
Member
Registered: 2015-10-26
Posts: 11

Re: Countdown timer in a terminal

Thanks

Offline

#3 2021-04-09 15:02:53

ohnonot
...again
Registered: 2015-09-29
Posts: 5,568

Re: Countdown timer in a terminal

Colonel Panic wrote:

... bash ... works in a terminal and counts down 20 seconds at a time ...

seconds=20; date1=$((`date +%s` + $seconds));
while [ "$date1" -ge `date +%s` ]; do
  echo -ne "$(date -u --date @$(($date1 - `date +%s` )) +%H:%M:%S)\r";
done

This is actually pretty resource intensive; adding a "sleep 0.1" already reduces the strain significantly.
But why call date twice in a loop over and over when all you want is to count down seconds...

seconds=20
end_seconds=$((SECONDS+seconds))
while ((SECONDS<end_seconds)); do
    printf ' %2d\r' "$((end_seconds-SECONDS))"
    sleep 0.1
done

see 'man bash' => Shell variables => SECONDS.


Give to COVAX! Here or here. (explanation)
My Repos: notabug | framagit

Offline

#4 2021-04-09 19:18:01

brontosaurusrex
Middle Office
Registered: 2015-09-29
Posts: 2,402
Website

Re: Countdown timer in a terminal

1. An zsh oneliner attempt

c=20; repeat c {(( c-- )); sleep 1; echo $c}

2. Similar, but countdown in single line

c=20; d="$c"; echo -ne "$c\r"; repeat c {(( c-- )); sleep 1; echo -ne "${(l(2)(0))c}\r"} && echo "$d seconds has passe
d."

3. A fun one that draws a little reverse staircase using perc2 script

c=20; set +m; perc=$(( 100.0/c )); perc2 100 & repeat c {(( c-- )); sleep 1 & var="$(perc2 $(( perc * c )))" ; wait; echo "$var" }

Note: set +m disables shell monitoring, so that it will not report subshell returns.

███████████████████████████████████████████████████████████████████████████▎
█████████████████████████████████████████████████████████████████▊
████████████████████████████████████████████████████████▍
███████████████████████████████████████████████
█████████████████████████████████████▋
████████████████████████████▎
██████████████████▊
█████████▍

p.s. Both examples will not achieve millisecond precision. To test:

time ( c=20; set +m; perc=$(( 100.0/c )); perc2 100 & repeat c {(( c-- )); sleep 1 & var="$(perc2 $(( perc * c )))" ; wait; echo "$var" } )
# returns: 20.156 total on this machine.

Last edited by brontosaurusrex (2021-04-11 09:05:09)

Online

#5 2021-04-11 04:17:23

ohnonot
...again
Registered: 2015-09-29
Posts: 5,568

Re: Countdown timer in a terminal

brontosaurusrex wrote:

p.s. Both examples will not achieve millisecond precision.

Because you rely on the sleep command to measure time; the other examples above actually measure the time (one with `date`, the other with the bash builtin SECONDS) while counting down.


Give to COVAX! Here or here. (explanation)
My Repos: notabug | framagit

Offline

#6 2021-04-11 07:38:30

brontosaurusrex
Middle Office
Registered: 2015-09-29
Posts: 2,402
Website

Re: Countdown timer in a terminal

Your version takes 19 seconds, so I guess It's superluminal? smile
edit: The ops version takes 20.238s
I win. 
Prettyfied script version (zsh) of my 2nd example. And a progress-bar version (also zsh).

Last edited by brontosaurusrex (2021-04-11 13:08:51)

Online

#7 2021-04-11 11:23:19

misko_2083
Member
Registered: 2016-05-24
Posts: 525

Re: Countdown timer in a terminal

^There is always timeout big_smile

#!/bin/bash

function _exit {
  stty sane
  echo -ne "\e[?25h"
}

trap "_exit" EXIT

echo -ne "\e[?25l"

function _main {
  function _pbar {
    let _progress=(${1}*100/${2}*100)/100
    let _done=(${_progress}*2)/10
    let _left=20-$_done
    _fill=$(printf "%${_done}s")
    _empty=$(printf "%${_left}s")
    printf "\r%s[%3d%%]%s\r" "${_fill// /▇}" "${_progress}" "${_empty// /▇}"
  }
_end=200
for _n in {200..0}
do
    sleep 0.1
    _pbar ${_n} ${_end}
done
}
export -f _main

timeout --signal INT  20s bash -c _main

They use force, to make you do, what the deciders, have decided you must do!

Offline

#8 2021-04-12 04:43:44

ohnonot
...again
Registered: 2015-09-29
Posts: 5,568

Re: Countdown timer in a terminal

brontosaurusrex wrote:

Your version takes 19 seconds, so I guess It's superluminal? smile
edit: The ops version takes 20.238s
I win. 
Prettyfied script version (zsh) of my 2nd example. And a progress-bar version (also zsh).

My version takes 19s because it stops 1s early.

But the logic of my argument stands: since you never know how long actual script execution takes, you cannot rely solely on the sleep delays to measure time. It will get less precise the longer it runs.
(My version also uses sleep, but only to keep it from taking 100% CPU, not to measure time.)

But whatever, just continue faffing around with your version. It sure is prettier.

Last edited by ohnonot (2021-04-12 04:45:24)


Give to COVAX! Here or here. (explanation)
My Repos: notabug | framagit

Offline

#9 2021-04-12 13:30:12

misko_2083
Member
Registered: 2016-05-24
Posts: 525

Re: Countdown timer in a terminal

ohnonot wrote:

you cannot rely solely on the sleep delays to measure time.

Yes, you can.

Most of the delay originates from writing to the terminal, not  from sleep command.
Sleep 1 is always one second. It's that printf adds extra time.

time sleep 1

real	0m1,004s
user	0m0,000s
sys	0m0,003s

Sleep does nothing else but sleeping.
So sleep is only wasting time, so to say. big_smile
That sleeping time can be spent in other ways,
e.g. printing to the terminal and counting seconds.
The trick is to to to run sleep in the background,
then move to the next command that writes to the terminal and wait until the subshell exits.

ctdown() {
  seconds=20
   while [ $seconds -gt 0 ] ; do
       sleep 1 &
       printf "\r%2d" "${seconds}"
       seconds=$((seconds-1))
       wait
   done  2>/dev/null
}
time ctdown
 1
real	0m20,073s
user	0m0,039s
sys	0m0,033s

Edit: It's fine for 20 seconds, on the other hand it's almost a second late on a 120second countdown.
Yours is preety accurate no matter what sleep time 1 or 0.1s with bronto's sleep.

ctdown() {
   seconds=120
   end_seconds=$((SECONDS+seconds))
   while ((SECONDS<end_seconds)); do
      sleep 1 &
      printf ' %3d\r' "$((end_seconds-SECONDS))"
      wait
done 2>/dev/null
}
time ctdown
   1
real	1m59,627s
user	0m0,208s
sys	0m0,216s

Even hurries a little.
Without a further delay, I declare a tie between Bronto and Not. big_smile

Last edited by misko_2083 (2021-04-12 15:04:51)


They use force, to make you do, what the deciders, have decided you must do!

Offline

#10 2021-04-12 16:40:40

brontosaurusrex
Middle Office
Registered: 2015-09-29
Posts: 2,402
Website

Re: Countdown timer in a terminal

Uhmm, ok, still you two are doing low-level stuff in bash script, my 1st script reports 0% cpu usage for example. I'am fine with tie, little reluctant, but ok wink

Online

#11 2021-04-12 19:02:05

misko_2083
Member
Registered: 2016-05-24
Posts: 525

Re: Countdown timer in a terminal

^Avoiding the zombie shell apocalypse.
You people aleady pulled your war axes. big_smile

Last edited by misko_2083 (2021-04-13 04:43:53)


They use force, to make you do, what the deciders, have decided you must do!

Offline

#12 2021-04-13 09:04:35

brontosaurusrex
Middle Office
Registered: 2015-09-29
Posts: 2,402
Website

Re: Countdown timer in a terminal

Doing some 'research', this one is neat (and correct and low cpu)
https://github.com/trehn/termdown (pip install termdown)

Similar in go (super correct)
https://github.com/antonmedv/countdown

time countdown 25s -up
countdown 25s -up  0.02s user 0.00s system 0% cpu 25.011 total

Last edited by brontosaurusrex (2021-04-13 09:23:28)

Online

#13 2021-04-17 23:53:04

Colonel Panic
Member
Registered: 2018-11-13
Posts: 370

Re: Countdown timer in a terminal

Good to see this thread's still going although I don't have the knowledge to contribute further. I haven't read all the posts yet but I like the two (termdown and countdown) brontosaurusrex has just mentioned.

Last edited by Colonel Panic (2021-04-17 23:53:24)

Offline

Board footer

Powered by FluxBB