Odpowiedzi:
Nie jestem pewien, dlaczego potrzebujesz beep
, jeśli wszystko, czego potrzebujesz, to stoper, możesz to zrobić:
while true; do echo -ne "`date`\r"; done
To pokaże sekundy w czasie rzeczywistym i możesz to 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ę chcesz naprawdę „formatu stopera”, w którym 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
W przypadku licznika czasu (który nie jest tym, o co pytałeś w pierwotnym pytaniu) możesz to zrobić (odpowiednio zmień 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 łączyć je w proste polecenia, używając funkcji bash (lub dowolnej powłoki, którą preferujesz). W bash dodaj te wiersze do swojego ~/.bashrc
( sleep 0.1
spowoduje to, że system będzie czekał przez 1/10 sekundy między każdym uruchomieniem, abyś nie spamował 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
}
Następnie możesz uruchomić minutnik odliczający minutę, uruchamiając:
countdown 60
Możesz odliczać dwie godziny dzięki:
countdown $((2*60*60))
lub cały dzień przy użyciu:
countdown $((24*60*60))
I uruchom stoper, uruchamiając:
stopwatch
Jeśli potrzebujesz umieć radzić sobie z dniami, 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
}
Pamiętaj, że stopwatch
funkcja nie była testowana od wielu dni, ponieważ tak naprawdę nie chciałem czekać na nią 24 godziny. Powinien działać, ale proszę dać mi znać, jeśli nie działa.
bash
, mogę z tym żyć (chociaż jest to wyższe niż się spodziewałem i dodałem też sen do własnego .bashrc).
date +%s
- $ data1)) +% H:% M:% S) ";
echo -ne "$(date -ju -f %s $(($date1 -
data +% s )) +%H:%M:%S)\r"
;
play -q -n synth 2 pluck C5
.
Mój ulubiony sposób to:
Początek:
time cat
Zatrzymać:
ctrl+c
Jak skomentował @wjandrea poniżej, należy uruchomić inną wersję:
time read
i naciśnij, Enter
aby zatrzymać
time read
time read
kończy się niepowodzeniem w Zsh, ale time (read)
działa.
Szukałem tego samego i ostatecznie napisałem coś bardziej skomplikowanego w Pythonie:
To da ci proste 10-sekundowe odliczanie:
sudo pip install termdown
termdown 10
Użyłem 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 .
sh-3.2# man leave
ustawić minutnik na 15 minut
sh-3.2# leave +0015
Alarm set for Thu Nov 3 14:19:31 CDT 2016. (pid 94317)
sh-3.2#
edytuj: Miałem kilka otwartych linków i pomyślałem, że to jest specyficzne dla OSX, przepraszam za to. Pozostawiając moją odpowiedź, aby inni byli świadomi urlopu na BSD.
To jest dla stopera z setnymi sekund:
#!/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
}
}
return $1
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 łatwiej jest zadzwonić (nie musisz robić matematyki), a także jest abstrakcyjne. Przykład zastosowania :
{ ~ } » 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 stylu timera pracy:
{ ~ } » 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 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
Oto kod do umieszczenia w .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 za pomocą wiersza poleceń Linuksa ) lub cygwin ( cat /path/foo.wav > /dev/dsp
działa dla mnie w babun / win7) i masz prosty elastyczny zegar z alarmem !
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 otrzymać sygnał, gdy osiągnie zero, może np. Zbudować go za pomocą polecenia, które zwróciło niezerowy status wyjścia na zero i połączyć go z watch -b
czymś innym, ale jeśli chce się zbudować bardziej skomplikowany skrypt, to prawdopodobnie nie taka droga; jest to bardziej „szybkie i brudne rozwiązanie typu single-liner”.
watch
Ogólnie podoba mi się ten program. Po raz pierwszy to zobaczyłem po tym, jak napisałem już niezliczoną liczbę while sleep 5; do
pętli do różnych efektów. watch
był wyraźnie ładniejszy.
W końcu napisałem własny skrypt 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
Dziwi mnie, że nikt nie używał tego sleepenh
narzędzia w swoich skryptach. Zamiast tego proponowane rozwiązania wykorzystują albo sleep 1
pomiędzy kolejnymi wyjściami timera, albo zajętą pętlą, która wysyła tak szybko, jak to możliwe. Ten pierwszy jest nieodpowiedni, ponieważ z uwagi na krótki czas drukowania, wydruk nie będzie się odbywał raz na sekundę, ale będzie nieco mniejszy niż ten, który nie jest optymalny. Po upływie wystarczającego czasu licznik przeskoczy o sekundę. Ta ostatnia jest nieodpowiednia, ponieważ powoduje, że procesor jest zajęty bez powodu.
Narzędzie, które mam, $PATH
wygląda następująco:
#!/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 jako stoper (odliczanie do przerwania) lub jako licznik czasu, który działa przez określony czas. Ponieważ sleep
polecenie jest używane, ten skrypt pozwala określić czas, przez który należy liczyć z taką samą dokładnością, jak sleep
pozwala. W przypadku Debiana i pochodnych obejmuje to snu poniżej sekundy i miły, czytelny dla człowieka sposób określania czasu. 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
Jak widać, polecenie działało dokładnie przez 2 minuty i 4,6 sekundy, bez dużej ilości magii w samym skrypcie.
EDYCJA :
Narzędzie sleepenh pochodzi z pakietu o tej samej nazwie w Debianie i jego pochodnych, takich jak Ubuntu. W przypadku dystrybucji, które go nie mają, pochodzi z https://github.com/nsc-deb/sleepenh
Zaletą Sleepenh jest to, że jest w stanie wziąć pod uwagę niewielkie opóźnienie, które kumuluje się w czasie od przetwarzania innych rzeczy niż sen podczas pętli. Nawet jeśli ktoś sleep 1
wykona tylko pętlę 10 razy, ogólne wykonanie zajmie trochę więcej niż 10 sekund z powodu niewielkiego narzutu związanego z wykonywaniem sleep
i iteracją pętli. Ten błąd powoli narasta i z czasem sprawi, że nasz stoper będzie coraz bardziej nieprecyzyjny. Aby rozwiązać ten problem, każda iteracja pętli musi obliczyć dokładny czas uśpienia, który zwykle jest nieco krótszy niż sekunda (dla timerów interwału 1-sekundowego). Narzędzie Sleepenh robi to za Ciebie.
sleep 0.1
. Co to jest sleepnh
(nie mogę go znaleźć w repozytoriach Arch) i czym się różni sleep
? O ile mogę stwierdzić, zasadniczo robisz to samo, co moja odpowiedź powyżej. czego mi brakuje?
sleep 5
polega na tym, że nie śpisz dokładnie przez 5 sekund. Spróbuj na przykład time sleep 5
i zobaczysz, że uruchomienie polecenia zajmuje nieco ponad 5 sekund. Z czasem błędy się kumulują. Narzędzie Sleepenh pozwala łatwo uniknąć gromadzenia się błędów.
sleepnh
jest lepszy niż sleep
(mówisz tylko, że inne odpowiedzi używają sleep 1
- a których nie , wykorzystuje to tylko OP) i ii) skąd go pobrać i jak go zainstalować, ponieważ nie jest to standardowe narzędzie.
sleep
oraz sleepenh
w pierwszym akapicie. W każdym razie, prawdopodobnie nie byłem wystarczająco jasny, więc rozwinąłem to bardziej na końcu. Problemy z dokładnością co do milisekund są takie same, jak w przypadku sleep
jednorazowego połączenia . Gromadzą się one z czasem i w pewnym momencie jest to zauważalne. Nie powiedziałem, że inni używają tylko sleep 1
. Powiedziałem, że używają sleep 1
albo busyloop. Co oni nadal robią. Pokaż mi licznik. Odpowiedzi, które sleep 0.1
to robią, są takie same, jak te, sleep 1
z wyjątkiem tego, że kumulują błędy jeszcze szybciej.
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 napisać coś bardzo zbliżonego do pytania OP, które osobiście zaakceptowałbym jako „ odliczanie onelinera w terminalu ”. Moimi celami były:
Jak to działa:
seq
drukuje liczby od 60 do 1.echo -ne "\r$i "
zwraca daszek na początek łańcucha i wypisuje bieżącą $i
wartość. Spacja po nim jest wymagana do zastąpienia poprzedniej wartości, jeśli była dłuższa o znaki niż bieżąca $i
(10 -> 9).Udawaj, że jesteś osobą w systemie OSX i szukasz stopera z linii poleceń. Udawaj, że nie chcesz instalować narzędzi GNU, a po prostu chcesz działać z Uniksemdate
w takim przypadku postępuj zgodnie z instrukcjami @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 + daty w czasie UTC. Możesz także zainstalować 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/
sw to prosty stoper, 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
Przykład python:
#!/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()
Jest to podobne do przyjętej odpowiedzi, ale terdon countdown()
dał mi błędy składniowe. Ten działa jednak dla mnie świetnie:
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 go włożyć, .bashrc
a następnie wykonać za pomocą: timer t
(gdzie t to czas w minutach).
Znalazłem to pytanie dzisiaj, szukając terminowej aplikacji do wyświetlania dużego licznika czasu dla warsztatu. Żadna z sugestii nie była dokładnie tym, czego potrzebowałem, więc szybko przygotowałem kolejną w Go: https://github.com/bnaucler/cdown
Ponieważ odpowiedź na to pytanie jest już wystarczająca, rozważ to dla potomności.
$ sen 1500 && xterm -fg żółty -g 240x80 &
Kiedy ten duży terminal z żółtym tekstem podskoczy, czas wstać i rozciągnąć się!
Uwagi: - 1500 sekund = 25 minut pomodoro - 240x80 = rozmiar terminala z rzędem 240 znaków i 80 rzędami. Widocznie wypełnia dla mnie ekran.
Źródło: http://www.linuxquestions.org/questions/linux-newbie-8/countdown-timer-for-linux-949463/
Wersja GUI stopera
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
Jeśli chcesz program kompilowany z dowolnego powodu, działałyby następujące czynności:
#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 << "\033[2A\033[K";
std::this_thread::sleep_for(milliseconds(100));
}
std::cout << "Finished" << std::endl;
return 0;
}
Można tego użyć w innych programach, a także łatwo przenosić, jeśli środowisko bash nie jest dostępne lub po prostu wolisz używać skompilowanego programu
.zshrc
zaraz po przeczytaniu twojej odpowiedzi. Dzisiaj użyłemcountdown
pierwszy raz i zauważyłem dość wysokie zużycie procesora. Dodałemsleep 0.1
(nie wiem, czy czas uśpienia ułamka sekundy jest obsługiwany we wszystkich systemach), co znacznie to poprawiło. Wadą jest oczywiście mniej dokładna dokładność wyświetlania, ale mogę żyć z odchyleniem maks. 100ms.