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

¿Hay alguna manera de mostrar un temporizador de cuenta atrás o cronómetro en un terminal?

¿Cómo puedo mostrar un temporizador de cuenta atrás en tiempo real en el terminal de Linux? ¿Existe una aplicación o, mejor aún, un programa para hacer esto?

Respuestas (22)

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

No estoy seguro de por qué necesitas beep, si todo lo que quieres es un cronómetro, puedes hacer esto:

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

Eso te mostrará los segundos que pasan en tiempo real y puedes pararlo con Ctrl+C. Si necesitas mayor precisión, puedes usar esto para obtener nanosegundos:

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

Finalmente, si realmente, realmente quieres el “formato de cronómetro”, donde todo comienza en 0 y empieza a crecer, podrías hacer algo como esto:

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

Para un temporizador de cuenta atrás (que no es lo que pedía tu pregunta original) podrías hacer esto (cambiando los segundos en consecuencia):

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

Puedes combinar estos en comandos simples usando las funciones de bash (o cualquier shell que prefieras). En bash, añada estas líneas a su ~/.bashrc (el sleep 0.1 hará que el sistema espere 1/10 de segundo entre cada ejecución para que no se sature 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
}

A continuación, puede iniciar una cuenta atrás de un minuto ejecutando:

countdown 60

Puede hacer una cuenta atrás de dos horas con:

countdown $((2*60*60))

o un día entero utilizando:

countdown $((24*60*60))

Y poner en marcha el cronómetro ejecutando:

stopwatch

Si necesitas poder manejar días además de horas, minutos y segundos, podrías hacer algo así:

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 que la función stopwatch no ha sido probada para días ya que no quería esperar 24 horas para ello. Debería funcionar pero, por favor, hazme saber si no lo hace.

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

Mi forma favorita es:

Inicio:

time cat

Parar:

ctrl+c

Como comenta @wjandrea más abajo, otra versión es ejecutar:

time read

y pulsar Enter para parar

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

Yo buscaba lo mismo y terminé escribiendo algo más elaborado en Python:

Esto te dará una simple cuenta atrás de 10 segundos:

sudo pip install termdown
termdown 10

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

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

poner un temporizador durante 15 minutos

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

editar: Tenía un montón de enlaces abiertos, y pensé que esto era específico para osx, lo siento. Dejando mi respuesta para que otros estén al tanto de la licencia en los BSD.

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

Yo he utilizado este:

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
)

Ejemplo:

countdown "00:07:55"

Aquí hay una fuente .

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

Esto es para un cronómetro con centésimas de segundo:

#!/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
  }
}

Ejemplo

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

Respuesta corta:

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

Explicación:

Sé que hay muchas respuestas, pero sólo quiero publicar algo muy cercano a la pregunta del OP, que personalmente aceptaría como efectivamente “ cuenta atrás en terminal”. Mis objetivos eran:

  1. One liner.
  2. Cuenta atrás.
  3. Fácil de recordar y de escribir en la consola (sin funciones y lógica pesada, sólo bash).
  4. No requiere instalar software adicional (se puede usar en cualquier servidor al que vaya por ssh, aunque no tenga root allí).

Cómo funciona:

  1. seq imprime números del 60 al 1.
  2. echo -ne "\r$i " devuelve el cursor al principio de la cadena e imprime el valor actual de $i. Se requiere un espacio después para sobrescribir el valor anterior, si era más largo en caracteres que el actual $i (10 -> 9).
4
4
4
2015-02-01 14:42:54 +0000

He combinado la respuesta del muy buen terdon, en una función que al mismo tiempo muestra el tiempo desde el inicio, y el tiempo hasta el final. También hay tres variantes para que sea más fácil de llamar (no tienes que hacer matemáticas en bash), y también está abstraído. Ejemplo de uso :

{ ~ } » 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

Y algo así como temporizador de trabajo:

{ ~ } » 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

Y si necesitas algún tiempo muy específico:

{ ~ } » 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

Aquí tienes el código para poner en tu . ¡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 esto con alguna forma de reproducir sonido en la terminal de linux reproducir mp3 o archivo wav a través de la línea de comandos de Linux ) o cygwin (cat /path/foo.wav > /dev/dsp me funciona en babun/win7) y tienes un simple temporizador flexible con alarma!

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

Terminé escribiendo mi propio script de 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

Me sorprende que nadie haya utilizado la herramienta sleepenh en sus scripts. En su lugar, las soluciones propuestas utilizan un sleep 1 entre las salidas subsiguientes del temporizador o un bucle ocupado que da salida lo más rápido posible. La primera es inadecuada porque debido al poco tiempo que se invierte en la impresión, la salida no se producirá realmente una vez por segundo sino un poco menos que eso, lo cual es subóptimo. Después de que haya pasado suficiente tiempo, el contador se saltará un segundo. Esto último es inadecuado porque mantiene a la CPU ocupada sin una buena razón.

La herramienta que tengo en mi $PATH se ve así:

#!/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

El script puede usarse como un cronómetro (contando hasta que se interrumpe) o como un temporizador que se ejecuta durante la cantidad de tiempo especificada. Dado que se utiliza el comando sleep, este script permite especificar la duración para la que contar con la misma precisión que permite su sleep. En Debian y derivados, esto incluye reposos de sub-segundos y una forma agradable y legible para los humanos de especificar el tiempo. Así, por ejemplo, puede decir

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

Y como puede ver, el comando se ejecutó exactamente durante 2 minutos y 4,6 segundos sin mucha magia en el propio script.

EDIT :

La herramienta sleepenh proviene del paquete del mismo nombre en Debian y sus derivados como Ubuntu. Para las distribuciones que no lo tienen, viene de https://github.com/nsc-deb/sleepenh

La ventaja de sleepenh es, que es capaz de tener en cuenta el pequeño retraso que se acumula en el tiempo por el procesamiento de otras cosas que el sueño durante un bucle. Incluso si uno sólo sleep 1 en un bucle 10 veces, la ejecución total tomaría un poco más de 10 segundos debido a la pequeña sobrecarga que viene de ejecutar sleep e iterar el bucle. Este error se acumula lentamente y con el tiempo haría que nuestro cronómetro fuera cada vez más impreciso. Para solucionar este problema, hay que calcular en cada iteración del bucle el tiempo preciso para dormir, que suele ser ligeramente inferior a un segundo (para los temporizadores de un segundo de intervalo). La herramienta sleepenh hace esto por ti.

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

Otro enfoque

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

Para Mac:

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

Si uno quiere una señal cuando llegue a cero, podría, por ejemplo, construirlo con un comando que devolviera un estado de salida distinto de cero y combinarlo con watch -b, o algo así, pero si uno quiere construir un script más elaborado, probablemente este no sea el camino a seguir; es más una solución del tipo “rápido y sucio de una sola línea”.

  • *

Me gusta el programa watch en general. Lo vi por primera vez después de haber escrito ya innumerables bucles while sleep 5; do a diferentes efectos. El watch era manifiestamente más bonito.

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

(https://github.com/coryfklein/sw) es un simple cronómetro que funcionará para siempre.

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

Instalación

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

Imagina que eres una persona en OSX que busca un cronómetro en línea de comandos. Imagina que no quieres instalar las herramientas gnu y solo quieres correr con el unix date

en ese caso haz lo que dice @terdon pero con esta modificación:

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

Echa un vistazo a TermTime , es un buen reloj y cronómetro basado en el terminal:

pip install termtime

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

Simplemente usa el reloj + la fecha en tiempo UTC. También puedes instalar algún paquete para la visualización en grande…

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'

¡Pruébalo!

Vea también http://www.cyberciti.biz/faq/create-large-colorful-text-banner-on-screen/

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

Para futuras referencias, existe una herramienta de línea de comandos llamada µTimer con opciones de línea de comandos muy sencillas para un temporizador de cuenta atrás/cuenta arriba.

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

Un ejemplo en 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 versión GUI del cronómetro

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

Encontré esta pregunta hoy mismo, cuando buscaba una aplicación a plazo para mostrar un gran temporizador de cuenta atrás para un taller. Ninguna de las sugerencias era exactamente lo que necesitaba, así que rápidamente armé otra en Go: https://github.com/bnaucler/cdown

Como la pregunta ya está suficientemente contestada, considere esto para la posteridad.

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

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

Cuando ese gran terminal con texto amarillo salta, ¡es hora de levantarse y estirarse!

Notas: - 1500 segundos = pomodoro de 25 minutos - 240x80 = tamaño del terminal con una fila de 240 caracteres, y 80 filas. A mí me llena notablemente la pantalla.

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

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

Esto es similar a la respuesta aceptada, pero el countdown() de terdon me daba errores de sintaxis. Sin embargo, esta me funciona muy bien:

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

Puedes ponerlo en .bashrc y luego ejecutarlo con: timer t (donde t es el tiempo en minutos).

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

Si desea un programa compilable por cualquier razón, lo siguiente funcionarí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;
}

Esto puede ser usado en otros programas también y fácilmente portado, si un entorno bash no está disponible o simplemente prefieres usar un programa compilado github