Risposte:
Non sono sicuro del motivo per cui hai bisogno beep
, se tutto ciò che vuoi è un cronometro, puoi farlo:
while true; do echo -ne "`date`\r"; done
Questo ti mostrerà i secondi che passano in tempo reale e puoi fermarlo con Ctrl+ C. Se hai bisogno di maggiore precisione, puoi usarlo per darti nanosecondi:
while true; do echo -ne "`date +%H:%M:%S:%N`\r"; done
Infine, se vuoi davvero "formato cronometro", dove tutto inizia da 0 e inizia a crescere, potresti fare qualcosa del genere:
date1=`date +%s`; while true; do
echo -ne "$(date -u --date @$((`date +%s` - $date1)) +%H:%M:%S)\r";
done
Per un conto alla rovescia (che non è quello che la tua domanda originale ti ha chiesto) potresti farlo (cambia i secondi di conseguenza):
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
Puoi combinarli in semplici comandi usando le funzioni bash (o qualunque shell tu preferisca). In bash, aggiungi queste righe al tuo ~/.bashrc
(il sleep 0.1
sistema farà attendere 1/10 di secondo tra ogni esecuzione in modo da non spammare la tua CPU):
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
}
È quindi possibile avviare un conto alla rovescia di un minuto eseguendo:
countdown 60
Puoi contare per due ore con:
countdown $((2*60*60))
o un'intera giornata usando:
countdown $((24*60*60))
E avvia il cronometro eseguendo:
stopwatch
Se devi essere in grado di gestire giorni, ore, minuti e secondi, potresti fare qualcosa del genere:
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
}
Si noti che la stopwatch
funzione non è stata testata per giorni poiché non volevo davvero aspettare 24 ore per questo. Dovrebbe funzionare, ma per favore fatemi sapere se non funziona.
bash
, posso conviverci (anche se è più alto di quanto mi aspettassi e ho anche aggiunto il sonno al mio .bashrc).
date +%s
- $ date1)) +% H:% M:% S) ";
echo -ne "$(date -ju -f %s $(($date1 -
data +% s )) +%H:%M:%S)\r"
;
play -q -n synth 2 pluck C5
.
Il mio modo preferito è:
Inizio:
time cat
Fermare:
ctrl+c
Come @wjandrea ha commentato di seguito, è necessario eseguire un'altra versione:
time read
e premere Enter
per interrompere
time read
time read
fallisce in zsh, ma time (read)
funziona.
Stavo cercando la stessa cosa e ho finito per scrivere qualcosa di più elaborato in Python:
Questo ti darà un semplice conto alla rovescia di 10 secondi:
sudo pip install termdown
termdown 10
Ho usato questo:
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
)
Esempio:
countdown "00:07:55"
Ecco una fonte .
sh-3.2# man leave
impostare un timer per 15 minuti
sh-3.2# leave +0015
Alarm set for Thu Nov 3 14:19:31 CDT 2016. (pid 94317)
sh-3.2#
modifica: Avevo un sacco di collegamenti aperti e ho pensato che fosse specifico per osx, mi dispiace per quello. Lasciando la mia risposta in modo che altri siano consapevoli del congedo per i BSD.
Questo è per un cronometro con centesimi di secondo:
#!/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
Ho combinato l'ottima risposta del terdon, in una funzione che mostra contemporaneamente il tempo dall'inizio e il tempo fino alla fine. Esistono anche tre varianti, quindi è più facile da chiamare (non è necessario eseguire calcoli matematici) ed è anche astratto. Esempio di utilizzo :
{ ~ } » 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
E qualcosa come il timer di lavoro:
{ ~ } » 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
E se hai bisogno di un tempo molto specifico:
{ ~ } » 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
Ecco il codice da inserire nel tuo .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]}))
}
Combina questo con un modo di riprodurre l'audio nel terminale Linux ( riproduci file mp3 o wav tramite riga di comando Linux ) o cygwin ( cat /path/foo.wav > /dev/dsp
funziona per me in babun / win7) e hai un semplice timer flessibile con allarme !
Un altro approccio
countdown=60 now=$(date +%s) watch -tpn1 echo '$((now-$(date +%s)+countdown))'
Per Mac:
countdown=60 now=$(date +%s) watch -tn1 echo '$((now-$(date +%s)+countdown))'
#no p option on mac for watch
Se si desidera un segnale quando colpisce zero, si potrebbe ad esempio costruirlo con un comando che ha restituito uno stato di uscita diverso da zero a zero e combinarlo con watch -b
, o qualcosa del genere, ma se si vuole costruire uno script più elaborato, questo è probabilmente non è la strada da percorrere; si tratta più di una soluzione di tipo "one-liner veloce e sporco".
Mi piace il watch
programma in generale. L'ho visto per la prima volta dopo aver già scritto innumerevoli while sleep 5; do
loop con diversi effetti. watch
era manifestamente più bello.
Ho finito per scrivere il mio script di shell: 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
Sono sorpreso che nessuno abbia usato lo sleepenh
strumento nei loro script. Al contrario, le soluzioni proposte utilizzano una sleep 1
tra le uscite timer successive o un loop occupato che emette il più velocemente possibile. Il primo è inadeguato perché a causa del piccolo tempo impiegato per la stampa, l'output in realtà non avverrà una volta al secondo, ma un po 'meno di quello che non è ottimale. Dopo che è trascorso abbastanza tempo, il contatore salterà un secondo. Quest'ultimo è inadeguato perché mantiene occupata la CPU senza una buona ragione.
Lo strumento che ho nei miei $PATH
assomiglia a questo:
#!/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
Lo script può essere utilizzato come cronometro (conteggio fino a quando non viene interrotto) o come timer che viene eseguito per il periodo di tempo specificato. Poiché sleep
viene utilizzato il comando, questo script consente di specificare la durata per la quale contare con la stessa precisione sleep
consentita. Su Debian e derivati, questo include dormite sub-seconde e un bel modo leggibile dall'uomo per specificare l'ora. Quindi ad esempio puoi dire:
$ time countdown 2m 4.6s
countdown 2m 4.6s 0.00s user 0.00s system 0% cpu 2:04.60 total
E come puoi vedere, il comando è stato eseguito esattamente per 2 minuti e 4,6 secondi senza molta magia nello script stesso.
MODIFICA :
Lo strumento sleepenh deriva dal pacchetto con lo stesso nome in Debian e dai suoi derivati come Ubuntu. Per le distribuzioni che non lo hanno, proviene da https://github.com/nsc-deb/sleepenh
Il vantaggio di sleepenh è che è in grado di tenere conto del piccolo ritardo che si accumula nel tempo dall'elaborazione di altre cose oltre al sonno durante un ciclo. Anche se uno lo facesse sleep 1
in un ciclo solo 10 volte, l'esecuzione complessiva richiederebbe un po 'più di 10 secondi a causa del piccolo sovraccarico derivante dall'esecuzione sleep
e dall'iterazione del ciclo. Questo errore si accumula lentamente e col tempo renderebbe il nostro cronometro sempre più impreciso. Per risolvere questo problema, ogni iterazione di loop deve calcolare il tempo preciso di sospensione che di solito è leggermente inferiore a un secondo (per i timer a intervallo di un secondo). Lo strumento sleepenh fa questo per te.
sleep 0.1
. Che cos'è sleepnh
(non riesco a trovarlo nei repository Arch) e in cosa differisce sleep
? Per quanto ne so, stai praticamente facendo la stessa cosa della mia risposta sopra. Cosa mi sto perdendo?
sleep 5
è che non dormi esattamente per 5 secondi. Prova ad esempio time sleep 5
e vedi che eseguire il comando richiede poco più di 5 secondi. Nel tempo gli errori si accumulano. L'utilità sleepenh consente di evitare facilmente questo accumulo di errori.
sleepnh
è meglio di sleep
(dici solo che usano altre risposte sleep 1
- che non fanno , solo l'OP lo utilizza) e ii) dove trovarlo e come installarlo poiché non è uno strumento standard.
sleep
e sleepenh
nel primo paragrafo. Comunque, probabilmente non ero abbastanza chiaro su questo, quindi alla fine mi sono espanso di più. I problemi di precisione in millisecondi sono ciò che si ottiene quando si chiama sleep
una volta. Si accumulano nel tempo e ad un certo punto è evidente. Non ho detto che altri usano solo sleep 1
. Ho detto che usano sleep 1
o un occupato. Che fanno ancora. Mostrami un contro esempio. Le risposte che fanno sleep 0.1
sono le stesse di quelle che fanno sleep 1
tranne che accumulano errori ancora più velocemente.
Risposta breve:
for i in `seq 60 -1 1` ; do echo -ne "\r$i " ; sleep 1 ; done
Spiegazione:
So che ci sono molte risposte, ma voglio solo pubblicare qualcosa di molto vicino alla domanda di OP, che personalmente accetterei come davvero " conto alla rovescia nel terminale ". I miei obiettivi erano:
Come funziona:
seq
stampa numeri da 60 a 1.echo -ne "\r$i "
riporta il punto di inserimento all'inizio della stringa e stampa il $i
valore corrente . Lo spazio dopo è necessario per sovrascrivere il valore precedente, se era più lungo di caratteri rispetto all'attuale $i
(10 -> 9).Fai finta di essere una persona su OSX alla ricerca di un cronometro da riga di comando. Fai finta di non voler installare gli strumenti gnu e vuoi solo eseguirlo con unixdate
in quel caso fai come dice @terdon ma con questa modifica:
function stopwatch(){
date1=`date +%s`;
while true; do
echo -ne "$(date -jf "%s" $((`date +%s` - $date1)) +%H:%M:%S)\r";
sleep 0.1
done
}
Basta usare watch + date in ora UTC. Puoi anche installare alcuni pacchetti per display di grandi dimensioni ...
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'
Provalo!
Vedi anche http://www.cyberciti.biz/faq/create-large-colorful-text-banner-on-screen/
sw è un semplice cronometro che funzionerà per sempre.
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
Un esempio di 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()
Questo è simile alla risposta accettata, ma terdon countdown()
mi ha dato errori di sintassi. Questo funziona alla grande per me, però:
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!"; }
Puoi inserirlo .bashrc
e quindi eseguire con: timer t
(dove t è il tempo in minuti).
Oggi ho trovato questa domanda prima, quando cercavo un'applicazione a termine per visualizzare un grande conto alla rovescia per un seminario. Nessuno dei suggerimenti era esattamente quello di cui avevo bisogno, quindi ne ho rapidamente messo un altro in Go: https://github.com/bnaucler/cdown
Poiché la domanda ha già una risposta sufficiente, considera che ciò è nell'interesse dei posteri.
$ sleep 1500 && xterm -fg yellow -g 240x80 &
Quando quel grande terminale con il testo giallo salta in alto, è ora di alzarsi e allungarsi!
Note: - 1500 secondi = 25 minuti pomodoro - 240x80 = dimensione terminale con una riga di 240 caratteri e 80 righe. Riempie notevolmente uno schermo per me.
Credito: http://www.linuxquestions.org/questions/linux-newbie-8/countdown-timer-for-linux-949463/
Una versione GUI del cronometro
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
Se desideri un programma compilabile per qualsiasi motivo, funzionerebbe quanto segue:
#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;
}
Questo può essere usato anche in altri programmi e facilmente trasferito, se un ambiente bash non è disponibile o preferisci semplicemente usare un programma compilato
.zshrc
destra dopo aver letto la tua risposta. Oggi ho usatocountdown
la prima volta e ho notato un utilizzo della CPU piuttosto elevato. Ho aggiunto unsleep 0.1
(non so se un tempo di sospensione di un secondo frazionario è supportato su tutti i sistemi) che ha migliorato molto. Lo svantaggio è ovviamente una precisione di visualizzazione meno accurata, ma posso vivere con una deviazione di max. 100ms.