Respostas:
Não sei por que você precisa beep
, se tudo o que você quer é um cronômetro, você pode fazer isso:
while true; do echo -ne "`date`\r"; done
Isso mostrará os segundos que passam em tempo real e você poderá interrompê-lo com Ctrl+ C. Se você precisar de maior precisão, poderá usar isso para fornecer nanossegundos:
while true; do echo -ne "`date +%H:%M:%S:%N`\r"; done
Por fim, se você realmente deseja "formato de cronômetro", onde tudo começa em 0 e começa a crescer, você pode fazer algo assim:
date1=`date +%s`; while true; do
echo -ne "$(date -u --date @$((`date +%s` - $date1)) +%H:%M:%S)\r";
done
Para um contador regressivo (que não é o que sua pergunta original pediu), você pode fazer isso (alterar os segundos de acordo):
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
Você pode combiná-los em comandos simples usando as funções bash (ou qualquer shell que você preferir). No bash, adicione essas linhas ao seu ~/.bashrc
( sleep 0.1
isso fará com que o sistema aguarde 1/10 de segundo entre cada execução para que você não faça spam na sua 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
}
Você pode iniciar um contador regressivo de um minuto executando:
countdown 60
Você pode contar duas horas com:
countdown $((2*60*60))
ou um dia inteiro usando:
countdown $((24*60*60))
E inicie o cronômetro executando:
stopwatch
Se você precisar lidar com dias, além de horas, minutos e segundos, poderá fazer algo assim:
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
}
Observe que a stopwatch
função não foi testada há dias, pois eu realmente não queria esperar 24 horas por ela. Deve funcionar, mas por favor me avise se não funcionar.
bash
, posso conviver com isso (embora seja maior do que eu esperava e também adicionei o sono ao meu .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
.
Minha maneira favorita é:
Começar:
time cat
Pare:
ctrl+c
Como o @wjandrea comentou abaixo, outra versão deve ser executada:
time read
e pressione Enter
para parar
time read
time read
falha no zsh, mas time (read)
funciona.
Eu estava procurando a mesma coisa e acabei escrevendo algo mais elaborado em Python:
Isso fornecerá uma contagem regressiva simples de 10 segundos:
sudo pip install termdown
termdown 10
Eu usei 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
)
Exemplo:
countdown "00:07:55"
Aqui está uma fonte .
sh-3.2# man leave
definir um temporizador por 15 minutos
sh-3.2# leave +0015
Alarm set for Thu Nov 3 14:19:31 CDT 2016. (pid 94317)
sh-3.2#
edit: Eu tinha um monte de links abertos, e eu pensei que isso era específico para osx, desculpe por isso. Deixando minha resposta para que outros estejam cientes da licença nos BSDs.
Isto é para um cronômetro com centésimos 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
Combinei a muito boa resposta do terdon, em uma função que ao mesmo tempo mostra o tempo desde o início e o tempo até o fim. Também existem três variantes, portanto é mais fácil chamar (você não precisa fazer bash math) e também é abstraído. Exemplo 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
E algo como temporizador de trabalho:
{ ~ } » 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 você precisar de um tempo muito 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
Aqui está o código para colocar no seu .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]}))
}
Combine isso com alguma maneira de reproduzir som no terminal linux ( reproduza arquivos mp3 ou wav via linha de comando do Linux ) ou cygwin ( cat /path/foo.wav > /dev/dsp
funciona para mim no babun / win7) e você terá um timer flexível e simples com alarme !
Outra abordagem
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
Se alguém quer um sinal quando atinge zero, pode-se, por exemplo, construí-lo com um comando que retorne um status de saída diferente de zero em zero e combiná-lo com watch -b
, ou algo assim, mas se você quiser criar um script mais elaborado, provavelmente isso não é o caminho a percorrer; é mais uma solução do tipo "rápido e sujo de uma linha".
Eu gosto do watch
programa em geral. Vi pela primeira vez depois de já ter escrito inúmeras while sleep 5; do
voltas com efeitos diferentes. watch
foi comprovadamente melhor.
Acabei escrevendo meu próprio script 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
Estou surpreso que ninguém tenha usado a sleepenh
ferramenta em seus scripts. Em vez disso, as soluções propostas usam um sleep 1
entre as saídas subsequentes do timer ou um loop ocupado que produz o mais rápido possível. A primeira é inadequada porque, devido ao pequeno tempo gasto na impressão, a saída não ocorre de fato uma vez por segundo, mas um pouco menos do que a subótima. Após um tempo suficiente, o contador pulará um segundo. O último é inadequado porque mantém a CPU ocupada sem um bom motivo.
A ferramenta que eu tenho na minha $PATH
aparência é assim:
#!/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
O script pode ser usado como um cronômetro (contando até a interrupção) ou como um cronômetro que é executado pelo período de tempo especificado. Como o sleep
comando é usado, este script permite especificar a duração pela qual contar com a mesma precisão que você sleep
permite. No Debian e derivados, isso inclui sub-segundos de espera e uma boa maneira legível por humanos para especificar a hora. Então, por exemplo, você pode dizer:
$ time countdown 2m 4.6s
countdown 2m 4.6s 0.00s user 0.00s system 0% cpu 2:04.60 total
E como você pode ver, o comando foi executado exatamente por 2 minutos e 4,6 segundos sem muita mágica no próprio script.
EDIT :
A ferramenta sleepenh vem do pacote com o mesmo nome no Debian e seus derivados como o Ubuntu. Para distribuições que não possuem, ele vem de https://github.com/nsc-deb/sleepenh
A vantagem do sono é que ele pode levar em consideração o pequeno atraso que se acumula ao longo do tempo do processamento de outras coisas além do sono durante um loop. Mesmo se alguém fizesse sleep 1
um loop apenas 10 vezes, a execução geral levaria um pouco mais de 10 segundos por causa da pequena sobrecarga resultante da execução sleep
e da iteração do loop. Esse erro se acumula lentamente e, com o tempo, tornaria nosso cronômetro cada vez mais impreciso. Para corrigir esse problema, é necessário que cada iteração de loop calcule o tempo preciso para dormir, que geralmente é um pouco menos de um segundo (para temporizadores de intervalo de um segundo). A ferramenta sleepenh faz isso por você.
sleep 0.1
. O que é sleepnh
(não consigo encontrá-lo nos repositórios do Arch) e como ele difere sleep
? Até onde eu sei, você está basicamente fazendo a mesma coisa que a minha resposta acima. o que estou perdendo?
sleep 5
é que você não dorme por exatamente 5 segundos. Tente, por exemplo, time sleep 5
e você verá que a execução do comando leva um pouco mais de 5 segundos. Com o tempo, os erros se acumulam. O utilitário sleepenh permite evitar facilmente esse acúmulo de erros.
sleepnh
é melhor do que sleep
(você apenas diz que outras respostas usam sleep 1
- o que elas não , apenas o OP usa isso) e ii) onde obtê-lo e como instalá-lo, pois não é uma ferramenta padrão.
sleep
e sleepenh
no primeiro parágrafo. De qualquer forma, eu provavelmente não estava claro o suficiente sobre isso, então expandi mais sobre isso no final. Os problemas de precisão em milissegundos são os que você obtém ao ligar sleep
uma vez. Eles se acumulam com o tempo e, em algum momento, é perceptível. Eu não disse que os outros usam apenas sleep 1
. Eu disse que eles usam sleep 1
ou um busyloop. O que eles ainda fazem. Mostre-me um exemplo contrário. As respostas sleep 0.1
são as mesmas que as respostas, sleep 1
exceto que acumulam erros ainda mais rapidamente.
Resposta curta:
for i in `seq 60 -1 1` ; do echo -ne "\r$i " ; sleep 1 ; done
Explicação:
Sei que há muitas respostas, mas só quero postar algo muito próximo à pergunta do OP, que pessoalmente eu aceitaria como " contagem regressiva oneliner no terminal ". Meus objetivos eram:
Como funciona:
seq
imprime números de 60 a 1.echo -ne "\r$i "
retorna o sinal de intercalação para o início da sequência e imprime o $i
valor atual . Espaço depois que é necessário substituir o valor anterior, se for maior por caracteres do que o atual $i
(10 -> 9).Finja que você é uma pessoa do OSX procurando um cronômetro de linha de comando. Finja que você não deseja instalar as ferramentas gnu e apenas deseja executar com o unixdate
nesse caso, faça como o @terdon diz, mas com esta modificação:
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 usar o relógio + data no horário UTC. Você também pode instalar algum pacote para exibição 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'
Tente!
Consulte também http://www.cyberciti.biz/faq/create-large-colorful-text-banner-on-screen/
sw é um cronômetro simples que funcionará para 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
Um exemplo 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()
Isso é semelhante à resposta aceita, mas o Terdon countdown()
me deu erros de sintaxe. Este funciona muito bem para mim, no entanto:
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!"; }
Você pode inseri-lo .bashrc
e executar com: timer t
(onde t é o tempo em minutos).
Encontrei essa pergunta hoje mais cedo, ao procurar um aplicativo de termo para exibir um grande cronômetro de contagem regressiva para um workshop. Nenhuma das sugestões era exatamente o que eu precisava, então rapidamente montei outra em Go: https://github.com/bnaucler/cdown
Como a pergunta já está suficientemente respondida, considere que isso é uma questão de posteridade.
$ sleep 1500 && xterm -fg amarelo -g 240x80 &
Quando esse grande terminal com texto amarelo saltar, é hora de levantar e esticar!
Notas: - 1500 segundos = pomodoro de 25 minutos - 240x80 = tamanho do terminal com linha de 240 caracteres e 80 linhas. Preenche uma tela para mim visivelmente.
Crédito: http://www.linuxquestions.org/questions/linux-newbie-8/countdown-timer-for-linux-949463/
Uma versão GUI do 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
Se você desejar um programa compilável por qualquer motivo, o seguinte funcionará:
#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;
}
Isso também pode ser usado em outros programas e facilmente transportado, se um ambiente bash não estiver disponível ou se você preferir usar um programa compilado
.zshrc
direita depois de ler sua resposta. Hoje eu useicountdown
a primeira vez e notei um uso bastante alto da CPU. Eu adicionei umsleep 0.1
(não sei se um tempo de sono de um segundo fracionário é suportado em todos os sistemas), o que melhorou bastante. A desvantagem é, obviamente, uma precisão de exibição menos precisa, mas posso viver com um desvio de no máximo. 100ms.