Respuestas:
No estoy seguro de por qué lo necesita beep
, si todo lo que quiere es un cronómetro, puede hacer esto:
while true; do echo -ne "`date`\r"; done
Eso le mostrará los segundos que pasan en tiempo real y puede detenerlo con Ctrl+ C. Si necesita mayor precisión, puede usar esto para darle nanosegundos:
while true; do echo -ne "`date +%H:%M:%S:%N`\r"; done
Finalmente, si realmente quieres el "formato de cronómetro", donde todo comienza en 0 y comienza a crecer, puedes 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 regresiva (que no es lo que pidió su pregunta original), puede hacer esto (cambiar 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
Puede combinarlos en comandos simples usando las funciones bash (o el shell que prefiera). En bash, agregue estas líneas a su ~/.bashrc
(esto sleep 0.1
hará que el sistema espere 1/10 de segundo entre cada ejecución para que no envíe spam a su 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
}
Luego puede iniciar un temporizador de cuenta regresiva de un minuto ejecutando:
countdown 60
Puede realizar una cuenta regresiva de dos horas con:
countdown $((2*60*60))
o un día entero usando:
countdown $((24*60*60))
Y comience el cronómetro ejecutando:
stopwatch
Si necesita poder lidiar con días, horas, minutos y segundos, puede hacer algo como esto:
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
}
Tenga en cuenta que la stopwatch
función no se ha probado durante días, ya que realmente no quería esperar 24 horas. Debería funcionar, pero avíseme si no es así.
bash
, puedo vivir con eso (aunque es más alto de lo que esperaba y también he agregado el sueño a mi propio .bashrc).
date +%s
- $ date1)) +% H:% M:% S) ";
echo -ne "$(date -ju -f %s $(($date1 -
fecha +% s )) +%H:%M:%S)\r"
;
play -q -n synth 2 pluck C5
.
Mi forma favorita es:
Comienzo:
time cat
Detener:
ctrl+c
Como @wjandrea comentó a continuación, se ejecutará otra versión:
time read
y presione Enter
para detener
time read
time read
falla en zsh, pero time (read)
funciona.
Estaba buscando lo mismo y terminé escribiendo algo más elaborado en Python:
Esto te dará una simple cuenta regresiva de 10 segundos:
sudo pip install termdown
termdown 10
He usado 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 .
sh-3.2# man leave
establecer un temporizador para 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 de osx, lo siento. Dejando mi respuesta para que otros estén al tanto de la licencia en los BSD.
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
}
}
return $1
He combinado la muy buena respuesta del terdon, en una función que al mismo tiempo muestra la hora desde el inicio y el tiempo hasta el final. También hay tres variantes, por lo que es más fácil llamar (no tienes que hacer matemáticas bash), y también es abstracto. 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 el 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 un 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í está el código para poner en su .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 ( reproduce archivos mp3 o wav a través de la línea de comando de Linux ) o cygwin ( cat /path/foo.wav > /dev/dsp
funciona para mí en babun / win7) y tienes un temporizador flexible simple con alarma .
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 se quiere una señal cuando llega a cero, se podría construir, por ejemplo, con un comando que devolviera un estado de salida distinto de cero en cero y combinarlo con watch -b
algo, o algo así, pero si se quiere construir un script más elaborado, esto probablemente sea no es el camino a seguir; es más una solución de tipo "rápido y sucio".
Me gusta el watch
programa en general. Lo vi por primera vez después de haber escrito innumerables while sleep 5; do
bucles con diferentes efectos. watch
fue demostrablemente más agradable.
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
Me sorprende que nadie haya usado la sleepenh
herramienta en sus scripts. En cambio, las soluciones propuestas usan un sleep 1
entre salidas de temporizador posteriores o un bucle ocupado que sale lo más rápido posible. La primera es inadecuada porque debido al poco tiempo que se dedica a imprimir, la salida no se realizará realmente una vez por segundo, sino un poco menos de lo que no es óptimo. Después de que pase suficiente tiempo, el contador saltará un segundo. Este último es inadecuado porque mantiene ocupada la CPU sin una buena razón.
La herramienta que tengo en mi se $PATH
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 el tiempo especificado. Como sleep
se usa el comando, este script permite especificar la duración para la cual contar con la misma precisión que sleep
permite. En Debian y derivados, esto incluye durmientes de menos de un segundo y una buena forma legible por humanos para especificar el tiempo. Entonces, por ejemplo, puedes 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 guión mismo.
EDITAR :
La herramienta Sleepenh proviene del paquete del mismo nombre en Debian y sus derivados como Ubuntu. Para las distribuciones que no lo tienen, proviene 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 con el tiempo por el procesamiento de otras cosas además del sueño durante un ciclo. Incluso si uno solo realizara sleep 1
un bucle 10 veces, la ejecución general tomaría un poco más de 10 segundos debido a la pequeña sobrecarga que proviene de ejecutar sleep
e iterar el bucle. Este error se acumula lentamente y con el tiempo hará que nuestro cronómetro sea cada vez más impreciso. Para solucionar este problema, cada iteración del ciclo debe calcular el tiempo preciso para dormir, que generalmente es un poco menos de un segundo (para temporizadores de intervalo de un segundo). La herramienta Sleepenh hace esto por usted.
sleep 0.1
. ¿Qué es sleepnh
(no puedo encontrarlo en los repositorios de Arch) y en qué se diferencia sleep
? Por lo que puedo decir, básicamente estás haciendo lo mismo que mi respuesta anterior. ¿Qué me estoy perdiendo?
sleep 5
es que no duermes exactamente 5 segundos. Pruebe por ejemplo time sleep 5
y verá que ejecutar el comando tarda un poco más de 5 segundos. Con el tiempo se acumulan los errores. La utilidad sleepenh permite evitar fácilmente esta acumulación de errores.
sleepnh
es mejor que sleep
(solo dice que otras respuestas usan sleep 1
, que no lo hacen) , solo el OP usa eso) y ii) dónde obtenerlo y cómo instalarlo, ya que no es una herramienta estándar.
sleep
y sleepenh
en el primer párrafo. De todos modos, probablemente no estaba lo suficientemente claro sobre eso, así que me expandí más al final. Los problemas de precisión de milisegundos son los que se obtienen al llamar sleep
una vez. Se acumulan con el tiempo y en algún momento es notable. No dije que otros solo usan sleep 1
. Dije que usan sleep 1
o un busyloop. Lo que aún hacen. Muéstrame un contraejemplo. Las respuestas que hacen sleep 0.1
son las mismas que las que hacen, sleep 1
excepto que acumulan errores aún más rápido.
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 solo quiero publicar algo muy cercano a la pregunta de OP, que personalmente aceptaría como " cuenta regresiva en línea en la terminal ". Mis metas fueron:
Cómo funciona:
seq
imprime números del 60 al 1.echo -ne "\r$i "
devuelve el cursor al comienzo de la cadena e imprime el $i
valor actual . Espacio después de que se requiere para sobrescribir el valor anterior, si fue más largo en caracteres que el actual $i
(10 -> 9).Imagina que eres una persona en OSX que busca un cronómetro de línea de comandos. Imagina que no quieres instalar las herramientas de GNU y solo quieres ejecutar con el Unixdate
en ese caso, haga 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
}
Simplemente use watch + date en hora UTC. También puede instalar algún paquete para pantalla 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'
¡Intentalo!
Ver también http://www.cyberciti.biz/faq/create-large-colorful-text-banner-on-screen/
sw es un cronómetro simple que funcionará para siempre.
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 ejemplo de 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()
Esto es similar a la respuesta aceptada, pero terdon countdown()
me dio errores de sintaxis. Sin embargo, este funciona muy bien para mí:
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!"; }
Puede ponerlo .bashrc
y luego ejecutarlo con: timer t
(donde t es tiempo en minutos).
Encontré esta pregunta hoy, cuando buscaba una aplicación de término para mostrar un temporizador de cuenta regresiva grande para un taller. Ninguna de las sugerencias era exactamente lo que necesitaba, por lo que rápidamente puse otra en Go: https://github.com/bnaucler/cdown
Como la pregunta ya está suficientemente respondida, considere que esto es por el bien de la posteridad.
$ sleep 1500 && xterm -fg amarillo -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 de terminal con fila de 240 caracteres y 80 filas. Llena una pantalla para mí notablemente.
Crédito: http://www.linuxquestions.org/questions/linux-newbie-8/countdown-timer-for-linux-949463/
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
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 << "\033[2A\033[K";
std::this_thread::sleep_for(milliseconds(100));
}
std::cout << "Finished" << std::endl;
return 0;
}
Esto se puede usar en otros programas también y se puede portar fácilmente, si un entorno bash no está disponible o simplemente prefiere usar un programa compilado
.zshrc
derecha después de leer su respuesta. Hoy usécountdown
la primera vez y noté un uso bastante alto de la CPU. Agregué unsleep 0.1
(no sé si un tiempo de reposo de un segundo fraccional es compatible con todos los sistemas) que mejoró mucho eso. El inconveniente es, por supuesto, una precisión de visualización menos precisa, pero puedo vivir con una desviación máxima. 100ms.