2013-06-24 20:13:51 +0000 2013-06-24 20:13:51 +0000
157
157

Czy istnieje sposób na wyświetlenie timera odliczającego lub stopera w terminalu?

Jak mogę wyświetlić licznik czasu rzeczywistego w terminalu Linuksa? Czy istnieje jakaś istniejąca aplikacja lub, jeszcze lepiej, one liner, który to zrobi?

Odpowiedzi (22)

195
195
195
2013-06-24 22:11:13 +0000

Nie jestem pewien, dlaczego potrzebujesz beep, jeśli wszystko, czego chcesz, to stoper, możesz zrobić tak:

while true; do echo -ne "`date`\r"; done

To pokaże ci sekundy mijające w czasie rzeczywistym i możesz go zatrzymać za pomocą Ctrl+C. Jeśli potrzebujesz większej precyzji, możesz użyć tego, aby uzyskać nanosekundy:

while true; do echo -ne "`date +%H:%M:%S:%N`\r"; done

Wreszcie, jeśli naprawdę, naprawdę chcesz “formatu stopera”, gdzie wszystko zaczyna się od 0 i zaczyna rosnąć, możesz zrobić coś takiego:

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

Dla timera odliczającego (który nie jest tym, o co pytało twoje oryginalne pytanie) mógłbyś zrobić to (zmień odpowiednio sekundy):

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

Możesz połączyć je w proste polecenia, używając funkcji bash (lub dowolnej powłoki, którą preferujesz). W bashu dodaj te linie do swojego ~/.bashrc (sleep 0.1 sprawi, że system będzie czekał 1/10 sekundy pomiędzy każdym uruchomieniem, więc nie zaśmiecasz procesora):

function countdown(){
   date1=$((`date +%s` + $1)); 
   while ["$date1" -ge `date +%s`]; do 
     echo -ne "$(date -u --date @$(($date1 - `date +%s`)) +%H:%M:%S)\r";
     sleep 0.1
   done
}
function stopwatch(){
  date1=`date +%s`; 
   while true; do 
    echo -ne "$(date -u --date @$((`date +%s` - $date1)) +%H:%M:%S)\r"; 
    sleep 0.1
   done
}

Możesz następnie rozpocząć odliczanie jednej minuty uruchamiając:

countdown 60

Możesz odliczać dwie godziny za pomocą:

countdown $((2*60*60))

lub cały dzień używając:

countdown $((24*60*60))

I uruchomić stoper uruchamiając:

stopwatch

Jeśli potrzebujesz mieć do czynienia z dniami, jak również godzinami, minutami i sekundami, możesz zrobić coś takiego:

countdown(){
    date1=$((`date +%s` + $1));
    while ["$date1" -ge `date +%s`]; do 
    ## Is this more than 24h away?
    days=$(($(($(( $date1 - $(date +%s))) * 1 ))/86400))
    echo -ne "$days day(s) and $(date -u --date @$(($date1 - `date +%s`)) +%H:%M:%S)\r"; 
    sleep 0.1
    done
}
stopwatch(){
    date1=`date +%s`; 
    while true; do 
    days=$(( $(($(date +%s) - date1)) / 86400 ))
    echo -ne "$days day(s) and $(date -u --date @$((`date +%s` - $date1)) +%H:%M:%S)\r";
    sleep 0.1
    done
}

Zauważ, że funkcja stopwatch nie została przetestowana dla dni, ponieważ tak naprawdę nie chciałem czekać na nią 24 godziny. Powinna działać, ale proszę dać mi znać, jeśli tak nie jest.

100
100
100
2015-03-30 08:26:08 +0000

Mój ulubiony sposób to:

Start:

time cat

Stop:

ctrl+c

Jak skomentował poniżej @wjandrea, inną wersją jest uruchomienie:

time read

i nacisnąć Enter aby się zatrzymać

46
46
46
2014-06-06 07:06:57 +0000

Szukałem tego samego i skończyło się na napisaniu czegoś bardziej wyszukanego w Pythonie:

To da ci proste 10-sekundowe odliczanie:

sudo pip install termdown
termdown 10

Źródło: https://github.com/trehn/termdown

14
14
14
2016-11-03 19:06:37 +0000
sh-3.2# man leave

ustaw timer na 15 minut

sh-3.2# leave +0015
Alarm set for Thu Nov 3 14:19:31 CDT 2016. (pid 94317)
sh-3.2#

edit: Miałem kilka otwartych linków i myślałem, że to jest specyficzne dla osx, przepraszam za to. Pozostawiam moją odpowiedź, aby inni byli świadomi opuszczenia na BSD.

13
13
13
2013-06-26 19:52:03 +0000

Używam tego:

countdown()
(
  IFS=:
  set -- $*
  secs=$(( ${1#0} * 3600 + ${2#0} * 60 + ${3#0} ))
  while [$secs -gt 0]
  do
    sleep 1 &
    printf "\r%02d:%02d:%02d" $((secs/3600)) $(( (secs/60)%60)) $((secs%60))
    secs=$(( $secs - 1 ))
    wait
  done
  echo
)

Przykład:

countdown "00:07:55"

Oto źródło .

6
6
6
2013-12-29 05:42:56 +0000

To jest dla stopera z setnymi częściami sekundy:

#!/usr/bin/awk -f
function z() {
  getline < "/proc/uptime"
  close("/proc/uptime")
  return $0
}
BEGIN {
  x = z()
  while (1) {
    y = z()
    printf "%02d:%05.2f\r", (y - x) / 60, (y - x) % 60
  }
}

Przykład

5
5
5
2019-06-05 10:48:15 +0000

Krótka odpowiedź:

for i in `seq 60 -1 1` ; do echo -ne "\r$i " ; sleep 1 ; done

Wyjaśnienie:

Wiem, że jest wiele odpowiedzi, ale chcę tylko zamieścić coś bardzo bliskiego pytaniu OP, które osobiście zaakceptowałbym jako rzeczywiście “ oneliner countdown w terminalu”. Moje cele były następujące:

  1. One liner.
  2. Odliczanie.
  3. Łatwy do zapamiętania i wpisania w konsoli (bez funkcji i ciężkiej logiki, tylko bash).
  4. Nie wymaga dodatkowego oprogramowania do instalacji (może być używany na każdym serwerze, na który wejdę przez ssh, nawet jeśli nie mam tam roota).

Jak to działa:

  1. seq wypisuje liczby od 60 do 1.
  2. echo -ne "\r$i " zwraca kursor na początek łańcucha i wypisuje aktualną wartość $i. Spacja po niej jest wymagana do nadpisania poprzedniej wartości, jeżeli była ona dłuższa o znaki od bieżącej wartości $i (10 - 9).
4
4
4
2015-02-01 14:42:54 +0000

Połączyłem bardzo dobrą odpowiedź terdona, w funkcję, która jednocześnie wyświetla czas od początku i czas do końca. Istnieją również trzy warianty, więc jest to łatwiejsze do wywołania (nie trzeba robić matematyki w bashu), a także jest to wyabstrahowane. Przykład użycia :

{ ~ } » time_minutes 15
Counting to 15 minutes
Start at 11:55:34 Will finish at 12:10:34
     Since start: 00:00:08 Till end: 00:14:51

I coś w rodzaju work timera:

{ ~ } » time_hours 8
Counting to 8 hours
Start at 11:59:35 Will finish at 19:59:35
     Since start: 00:32:41 Till end: 07:27:19

A jeśli potrzebujesz jakiegoś bardzo konkretnego czasu:

{ ~ } » time_flexible 3:23:00
Counting to 3:23:00 hours
Start at 12:35:11 Will finish at 15:58:11
     Since start: 00:00:14 Till end: 03:22:46

Tutaj jest kod do umieszczenia w twoim . bashrc

function time_func()
{
   date2=$((`date +%s` + $1));
   date1=`date +%s`;
   date_finish="$(date --date @$(($date2)) +%T )"

   echo "Start at `date +%T` Will finish at $date_finish"

    while ["$date2" -ne `date +%s`]; do
     echo -ne " Since start: $(date -u --date @$((`date +%s` - $date1)) +%H:%M:%S) Till end: $(date -u --date @$(($date2 - `date +%s`)) +%H:%M:%S)\r";
     sleep 1
    done

    printf "\nTimer finished!\n"
    play_sound ~/finished.wav
}

function time_seconds()
{
  echo "Counting to $1 seconds"
  time_func $1
}

function time_minutes()
{
  echo "Counting to $1 minutes"
  time_func $1*60
}

function time_hours()
{
  echo "Counting to $1 hours"
  time_func $1*60*60
}

function time_flexible() # accepts flexible input hh:mm:ss
{
    echo "Counting to $1"
    secs=$(time2seconds $1)
    time_func $secs
}

function play_sound() # adjust to your system
{
    cat $1 > /dev/dsp
}

function time2seconds() # changes hh:mm:ss to seconds, found on some other stack answer
{ 
    a=( ${1//:/ }) 
    echo $((${a[0]}*3600+${a[1]}*60+${a[2]})) 
}

Połącz to z jakimś sposobem odtwarzania dźwięku w terminalu linuksowym (odtwarzaj pliki mp3 lub wav z linii komend linuksa)(https://superuser.com/questions/276596/play-mp3-or-wav-file-via-linux-command-line)) lub cygwin (cat /path/foo.wav > /dev/dsp działa dla mnie w babun/win7) i masz prosty, elastyczny timer z alarmem!

3
3
3
2013-06-25 00:40:38 +0000

Skończyło się na napisaniu mojego własnego skryptu powłoki: github gist

#!/bin/sh
# script to create timer in terminal
# Jason Atwood
# 2013/6/22

# start up
echo "starting timer script ..."
sleep 1 # seconds

# get input from user
read -p "Timer for how many minutes?" -e DURATION
DURATION=$(( $DURATION*60 )) # convert minutes to seconds

# get start time
START=$(date +%s)

# infinite loop
while [-1]; do
clear # clear window

# do math
NOW=$(date +%s) # get time now in seconds
DIF=$(( $NOW-$START )) # compute diff in seconds
ELAPSE=$(( $DURATION-$DIF )) # compute elapsed time in seconds
MINS=$(( $ELAPSE/60 )) # convert to minutes... (dumps remainder from division)
SECS=$(( $ELAPSE - ($MINS*60) )) # ... and seconds

# conditional
if [$MINS == 0] && [$SECS == 0] # if mins = 0 and secs = 0 (i.e. if time expired)
then # blink screen
for i in `seq 1 180`; # for i = 1:180 (i.e. 180 seconds)
do
clear # flash on
setterm -term linux -back red -fore white # use setterm to change background color
echo "00:00 " # extra tabs for visibiltiy

sleep 0.5

clear # flash off
setterm -term linux -default # clear setterm changes from above
echo "00:00" # (i.e. go back to white text on black background)
sleep 0.5
done # end for loop
break # end script

else # else, time is not expired
echo "$MINS:$SECS" # display time
sleep 1 # sleep 1 second
fi # end if
done # end while loop
3
3
3
2016-11-24 15:38:57 +0000

Jestem zaskoczony, że nikt nie użył narzędzia sleepenh w swoich skryptach. Zamiast tego, proponowane rozwiązania albo używają sleep 1 pomiędzy kolejnymi wyjściami timera, albo zajętej pętli, która wypisuje dane tak szybko, jak to tylko możliwe. To pierwsze rozwiązanie jest nieodpowiednie, ponieważ z powodu niewielkiego czasu poświęconego na wykonanie wydruku, wyjście nie będzie w rzeczywistości wykonywane raz na sekundę, ale trochę mniej niż raz, co jest nieoptymalne. Po upłynięciu odpowiedniej ilości czasu licznik pominie sekundę. To ostatnie jest nieodpowiednie, ponieważ utrzymuje procesor zajęty bez dobrego powodu.

Narzędzie, które mam w moim $PATH wygląda tak:

#!/bin/sh
if [$# -eq 0]; then
    TIMESTAMP=$(sleepenh 0)
    before=$(date +%s)
    while true; do
        diff=$(($(date +%s) - before))
        printf "%02d:%02d:%02d\r" $((diff/3600)) $(((diff%3600)/60)) $((diff%60))
        TIMESTAMP=$(sleepenh $TIMESTAMP 1.0);
    done
    exit 1 # this should never be reached
fi
echo "counting up to $@"
"$0" &
counterpid=$!
trap "exit" INT TERM
trap "kill 0" EXIT
sleep "$@"
kill $counterpid

Skrypt może być używany albo jako stoper (zliczający do momentu przerwania), albo jako timer, który działa przez określony czas. Ponieważ używana jest komenda sleep, skrypt ten pozwala określić czas, przez jaki ma liczyć, z taką samą precyzją, na jaką pozwala twoja komenda sleep. W Debianie i pochodnych, obejmuje to podsekundowe okresy uśpienia i czytelny dla człowieka sposób określania czasu. Tak więc na przykład możesz powiedzieć:

$ time countdown 2m 4.6s
countdown 2m 4.6s 0.00s user 0.00s system 0% cpu 2:04.60 total

I jak widać, polecenie działało dokładnie przez 2 minuty i 4,6 sekundy bez większej magii w samym skrypcie.

EDIT :

Narzędzie sleepenh pochodzi z pakietu o tej samej nazwie w Debianie i jego pochodnych jak Ubuntu. W dystrybucjach, które go nie posiadają, pochodzi ono z https://github.com/nsc-deb/sleepenh

Zaletą sleepenh jest to, że jest on w stanie uwzględnić małe opóźnienie, które gromadzi się w czasie z powodu przetwarzania innych rzeczy niż sleep podczas pętli. Nawet jeśli ktoś po prostu sleep 1 w pętli 10 razy, całkowite wykonanie zajęłoby trochę więcej niż 10 sekund z powodu małego narzutu, który pochodzi z wykonania sleep i iteracji pętli. Ten błąd powoli się kumuluje i z czasem sprawiłby, że nasz stoper byłby coraz bardziej niedokładny. Aby rozwiązać ten problem, musimy w każdej iteracji pętli obliczyć dokładny czas uśpienia, który zazwyczaj jest nieco mniejszy niż sekunda (dla jednosekundowych timerów). Narzędzie sleepenh robi to za Ciebie.

3
3
3
2014-08-21 19:13:05 +0000

Inne podejście

countdown=60 now=$(date +%s) watch -tpn1 echo '$((now-$(date +%s)+countdown))'

Dla Maca:

countdown=60 now=$(date +%s) watch -tn1 echo '$((now-$(date +%s)+countdown))'
#no p option on mac for watch

Jeśli ktoś chce sygnału, gdy trafi na zero, mógłby np. zbudować go za pomocą polecenia, które zwróciło niezerowy status wyjścia przy zerze i połączyć go z watch -b, lub coś takiego, ale jeśli ktoś chce zbudować bardziej rozbudowany skrypt, to prawdopodobnie nie jest to droga do zrobienia; jest to bardziej rozwiązanie typu “szybki i brudny one-liner”.


Ogólnie podoba mi się program watch. Po raz pierwszy zobaczyłem go po tym, jak napisałem już niezliczone pętle while sleep 5; do do różnych efektów. watch był ewidentnie ładniejszy.

3
3
3
2017-06-23 21:06:54 +0000

sw ](https://github.com/coryfklein/sw) jest prostym stoperem, który będzie działał wiecznie.

wget -q -O - http://git.io/sinister | sh -s -- -u https://raw.githubusercontent.com/coryfklein/sw/master/sw

Install

sw
 - start a stopwatch from 0, save start time in ~/.sw
sw [-r|--resume]
 - start a stopwatch from the last saved start time (or current time if no last saved start time exists)
 - "-r" stands for --resume

Usage

1
1
1
2015-04-13 12:34:57 +0000

Udawaj, że jesteś osobą na OSX szukającą stopera w linii poleceń. Udawaj, że nie chcesz instalować narzędzi gnu i chcesz po prostu działać z unixem date

w takim przypadku zrób tak jak mówi @terdon, ale z tą modyfikacją:

function stopwatch(){
    date1=`date +%s`; 
    while true; do 
        echo -ne "$(date -jf "%s" $((`date +%s` - $date1)) +%H:%M:%S)\r"; 
        sleep 0.1
    done
}
```.
1
1
1
2019-04-13 14:58:34 +0000

Spójrz na TermTime , jest to ładny zegar i stoper oparty na terminalu:

pip install termtime

1
1
1
2015-06-02 01:12:11 +0000

Wystarczy użyć zegarka + data w czasie UTC. Możesz również zainstalować jakiś pakiet dla dużego wyświetlacza…

export now="`date +%s -u`";
watch -n 0,1 'date +%T -u -d @$((`date +%s` - $now ))'

#Big plain characters
watch -n 0,1 'date +%T -u -d @$((`date +%s` - $now )) | toilet -f mono12'

#Big empty charaters
watch -n 0,1 'date +%T -u -d @$((`date +%s` - $now )) | figlet -c -f big'

Spróbuj!

Zobacz także http://www.cyberciti.biz/faq/create-large-colorful-text-banner-on-screen/

1
1
1
2014-09-26 15:21:48 +0000

Dla przyszłych odniesień, istnieje narzędzie wiersza poleceń o nazwie µTimer z bardzo prostymi opcjami wiersza poleceń dla timera odliczającego/odliczającego.

1
1
1
2014-02-13 12:00:38 +0000

Przykład w pythonie:

#!/usr/bin/python

def stopwatch ( atom = .01 ):
    import time, sys, math

    start = time.time()
    last = start
    sleep = atom/2
    fmt = "\r%%.%sfs" % (int(abs(round(math.log(atom,10)))) if atom<1 else "")
    while True:
        curr = time.time()
        subatom = (curr-last)
        if subatom>atom:
            # sys.stdout.write( "\r%.2fs" % (curr-start))
            sys.stdout.write( fmt % (curr-start))
            sys.stdout.flush()
            last = curr
        else:
            time.sleep(atom-subatom)

stopwatch()

0
0
0
2018-11-05 13:49:26 +0000

Stoper w wersji GUI

date1=`date +%s`
date1_f=`date +%H:%M:%S ____ %d/%m`
(
  while true; do 
    date2=$(date -u --date @$((`date +%s` - $date1)) +%H:%M:%S)
    echo "# started at $date1_f \n$date2"
  done
) |
zenity --progress \
  --title="Stop Watch" \
  --text="Stop Watch..." \
  --percentage=0
0
0
0
2016-12-08 20:20:14 +0000

Znalazłem to pytanie wcześniej dzisiaj, gdy szukałem aplikacji terminowej do wyświetlania dużego licznika odliczającego czas do warsztatu. Żadna z propozycji nie była dokładnie tym, czego potrzebowałem, więc szybko złożyłem kolejną w Go: https://github.com/bnaucler/cdown

Ponieważ pytanie jest już wystarczająco odpowiedziane, uznaj to za dla potomności.

0
0
0
2017-01-24 23:04:07 +0000

$ sleep 1500 && xterm -fg yellow -g 240x80 &

Kiedy ten duży terminal z żółtym tekstem podskoczy, czas wstać i się rozciągnąć!

Uwagi: - 1500 sekund = 25 minut pomodoro - 240x80 = rozmiar terminala z 240 znakowym wierszem, i 80 wierszami. Wypełnia ekran w sposób zauważalny dla mnie.

Kredyt: http://www.linuxquestions.org/questions/linux-newbie-8/countdown-timer-for-linux-949463/

0
0
0
2016-04-20 15:14:05 +0000

Jest to podobne do zaakceptowanej odpowiedzi, ale terdon’s countdown() dał mi błędy składni. Ten działa świetnie dla mnie, chociaż:

function timer() { case "$1" in -s) shift;; *) set $(($1 * 60));; esac; local S=" "; for i in $(seq "$1" -1 1); do echo -ne "$S\r $i\r"; sleep 1; done; echo -e "$S\rTime's up!"; }

Możesz umieścić go w .bashrc, a następnie wykonać z: timer t (gdzie t to czas w minutach).

-2
-2
-2
2014-08-18 17:19:37 +0000

Jeśli z jakiegokolwiek powodu chciałbyś mieć program nadający się do kompilacji, poniższe rozwiązanie będzie działać:

#include <iostream>
#include <string>
#include <chrono>

int timer(seconds count) {
  auto t1 = high_resolution_clock::now();
  auto t2 = t1+count;
  while ( t2 > high_resolution_clock::now()) {
    std::cout << "Seconds Left:" <<
    std::endl <<
      duration_cast<duration<double>>(count-(high_resolution_clock::now()-t1)).count() << 
    std::endl << "0x1&33[2A0x1&33[K";
    std::this_thread::sleep_for(milliseconds(100));
  }
  std::cout << "Finished" << std::endl;
  return 0;
}

To może być użyte również w innych programach i łatwo przeniesione, jeśli środowisko bash nie jest dostępne lub po prostu wolisz używać skompilowanego programu github