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

C'è un modo per visualizzare un timer con conto alla rovescia o cronometro in un terminale?

Come posso visualizzare un timer per il conto alla rovescia in tempo reale sul terminale Linux? C'è un'applicazione esistente o, ancora meglio, un one liner per fare questo?

Risposte (22)

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

Non sono sicuro del perché tu abbia bisogno di beep, se tutto quello che vuoi è un cronometro, puoi fare così:

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

Che vi mostrerà i secondi che passano in tempo reale e potete fermarlo con Ctrl+C. Se avete bisogno di maggiore precisione, potete usare questo per darvi i nanosecondi:

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

Infine, se volete davvero, davvero il “formato cronometro”, dove tutto parte da 0 e inizia a crescere, potreste fare qualcosa come questo:

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

Per un timer per il conto alla rovescia (che non è quello che la tua domanda originale chiedeva) potresti fare così (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 combinare questi in semplici comandi usando le funzioni di bash (o qualsiasi shell tu preferisca). In bash, aggiungete queste linee al vostro ~/.bashrc (lo sleep 0.1 farà attendere il sistema per 1/10 di secondo tra ogni esecuzione in modo da non spammare la 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
}

Puoi quindi avviare un timer per il conto alla rovescia di un minuto eseguendo:

countdown 60

Puoi fare un conto alla rovescia di due ore con:

countdown $((2*60*60))

o un giorno intero usando:

countdown $((24*60*60))

E avviare il cronometro eseguendo:

stopwatch

Se avete bisogno di poter gestire i giorni oltre a ore, minuti e secondi, potreste 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
}

Nota che la funzione stopwatch non è stata testata per i giorni poiché non volevo aspettare 24 ore. Dovrebbe funzionare, ma per favore fatemi sapere se non funziona.

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

Il mio modo preferito è:

Start:

time cat

Stop:

ctrl+c

Come @wjandrea ha commentato sotto, un'altra versione è quella di eseguire:

time read

e premere Enter per fermare

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

Stavo cercando la stessa cosa e ho finito per scrivere qualcosa di più elaborato in Python:

Questo vi darà un semplice conto alla rovescia di 10 secondi:

sudo pip install termdown
termdown 10

Fonte: https://github.com/trehn/termdown

14
14
14
2016-11-03 19:06:37 +0000
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#

edit: Avevo un mucchio di link aperti, e pensavo che questo fosse specifico per osx, mi dispiace. Lascio la mia risposta in alto in modo che gli altri siano consapevoli di lasciare sui BSD.

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

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 .

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

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
  }
}

Esempio

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

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 postare qualcosa di molto vicino alla domanda dell'OP, che personalmente accetterei come davvero “ conteggio alla rovescia nel terminale”. I miei obiettivi erano:

  1. One liner.
  2. Conto alla rovescia.
  3. Facile da ricordare e da digitare in console (senza funzioni e logica pesante, solo bash).
  4. Non richiede software aggiuntivo da installare (può essere utilizzato su qualsiasi server che vado via ssh, anche se non ho root lì).

Come funziona:

  1. seq stampa numeri da 60 a 1.
  2. echo -ne "\r$i " riporta il cursore all'inizio della stringa e stampa il valore corrente di $i. Lo spazio dopo di esso è necessario per sovrascrivere il valore precedente, se era più lungo di caratteri dell'attuale $i (10 -> 9).
4
4
4
2015-02-01 14:42:54 +0000

Ho combinato la risposta dell'ottimo terdon, in una funzione che allo stesso tempo visualizza il tempo dall'inizio, e il tempo fino alla fine. Ci sono anche tre varianti in modo che sia più facile da chiamare (non devi fare la matematica bash), 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 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 avete 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 mettere nel vostro . 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]})) 
}

Combinate questo con qualche modo di suonare nel terminale linux riprodurre file mp3 o wav tramite la linea di comando Linux ) o cygwin (cat /path/foo.wav > /dev/dsp funziona per me in babun/win7) e avrete un semplice timer flessibile con allarme!

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

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
3
3
3
2016-11-24 15:38:57 +0000

Sono sorpreso che nessuno abbia usato lo strumento sleepenh nei loro script. Invece, le soluzioni proposte o usano un sleep 1 tra le uscite successive del timer o un ciclo occupato che emette il più velocemente possibile. La prima è inadeguata perché a causa del poco tempo speso per fare la stampa, l'uscita non avverrà effettivamente una volta al secondo ma un po’ meno di quella, il che è subottimale. Dopo che è passato abbastanza tempo, il contatore salterà un secondo. Quest'ultimo è inadeguato perché tiene occupata la CPU senza una buona ragione.

Lo strumento che ho nel mio $PATH si presenta così:

#!/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 usato come un cronometro (contando fino a quando non viene interrotto) o come un timer che funziona per la quantità di tempo specificata. Poiché viene usato il comando sleep, questo script permette di specificare la durata per la quale contare con la stessa precisione consentita da sleep. Su Debian e derivate, questo include gli sleep sub-secondi e un bel modo leggibile dall'uomo per specificare il tempo. Così, per esempio, potete dire:

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

E come potete vedere, il comando ha funzionato esattamente per 2 minuti e 4,6 secondi senza molta magia nello script stesso.

EDIT :

Lo strumento sleepenh proviene dall'omonimo pacchetto in Debian e nelle sue derivate come Ubuntu. Per le distribuzioni che non ce l'hanno, viene 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 rispetto allo sleep durante un ciclo. Anche se uno facesse solo sleep 1 in un ciclo 10 volte, l'esecuzione complessiva richiederebbe un po’ più di 10 secondi a causa del piccolo overhead che deriva dall'esecuzione di sleep e dall'iterazione del ciclo. Questo errore si accumula lentamente e nel tempo renderebbe il nostro cronometro sempre più impreciso. Per risolvere questo problema, si deve calcolare ad ogni iterazione del ciclo il tempo preciso per dormire, che di solito è un po’ meno di un secondo (per timer con intervallo di un secondo). Lo strumento sleepenh fa questo per voi.

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

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 vuole un segnale quando arriva a zero, si potrebbe ad esempio costruire con un comando che restituisca uno stato di uscita non nullo a zero e combinarlo con watch -b, o qualcosa del genere, ma se si vuole costruire uno script più elaborato, questa probabilmente non è la strada da seguire; è più una soluzione del tipo “quick and dirty one-liner”.


Mi piace il programma watch in generale. L'ho visto per la prima volta dopo aver già scritto innumerevoli loop while sleep 5; do per diversi effetti. watch era dimostrabilmente più bello.

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

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

Installa

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

Uso

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

Fate finta di essere una persona su OSX che cerca un cronometro da linea di comando. Fate finta di non voler installare gli strumenti di Gnu e di voler solo funzionare con l'unix date

in questo caso fate 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
}
1
1
1
2019-04-13 14:58:34 +0000

Date un'occhiata a TermTime , è un bell'orologio e cronometro basato sul terminale:

pip install termtime

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

Basta usare l'orologio + la data in ora UTC. Puoi anche installare qualche pacchetto per una grande visualizzazione…

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'

Prova!

Vedi anche http://www.cyberciti.biz/faq/create-large-colorful-text-banner-on-screen/

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

Per riferimento futuro, c'è uno strumento a riga di comando chiamato µTimer con opzioni a riga di comando molto semplici per un timer di conto alla rovescia/conteggio.

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

Un esempio 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()

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

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
0
0
0
2016-12-08 20:20:14 +0000

Ho trovato questa domanda oggi, mentre cercavo un'applicazione a termine per visualizzare un grande timer per il conto alla rovescia per un workshop. Nessuno dei suggerimenti era esattamente quello di cui avevo bisogno, quindi ne ho rapidamente messo insieme un altro in Go: https://github.com/bnaucler/cdown

Visto che la domanda ha già una risposta sufficiente, considerala per i posteri.

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

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

Quando quel grande terminale con il testo giallo salta, è ora di alzarsi e fare stretching!

Note: - 1500 secondi = 25 minuti di pomodoro - 240x80 = dimensione del terminale con riga di 240 caratteri, e 80 righe. Riempie sensibilmente uno schermo per me.

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

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

Questo è simile alla risposta accettata, ma terdon’s countdown() mi dava errori di sintassi. Questa però funziona benissimo per me:

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!"; }

Si può mettere in .bashrc e poi eseguire con: timer t (dove t è il tempo in minuti).

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

Se volete un programma compilabile per qualsiasi motivo, il seguente funzionerebbe:

#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;
}

Questo può essere usato anche in altri programmi e facilmente portato, se un ambiente bash non è disponibile o semplicemente preferite usare un programma compilato github