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?
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?
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.
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.
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 .
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
}
}
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:
Jak to działa:
seq
wypisuje liczby od 60 do 1. 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).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!
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
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.
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.
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
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
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
}
```.
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/
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()
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
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.
$ 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/
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).
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