Question Est-il possible d'afficher un compte à rebours ou un chronomètre dans un terminal?


Comment afficher un compte à rebours en temps réel sur le terminal Linux? Existe-t-il une application existante ou, mieux encore, une application unique?


122
2018-06-24 20:13


origine


en ce qui concerne la cale SU: Je pense que cela relève du "logiciel informatique" sans "demander un achat ou une recommandation de produit". Je ne demande pas de recommandations; Je demande si quelque chose existe même. Lorsque j'ai posé la question, je m'attendais peut-être à un "oui, il y a ce script -nix intégré". Si je peux restructurer la question, je le ferai. - tir38
C'est ce que j'ai essayé de faire. Il est sur le sujet après mon édition en ce qui me concerne et j'ai voté pour la rouvrir. - terdon
@terdon merci, je vois comment c'est une meilleure question. - tir38


Réponses:


Je ne sais pas pourquoi tu as besoin beep, si tout ce que vous voulez est un chronomètre, vous pouvez le faire:

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

Cela vous montrera les secondes passées en temps réel et vous pouvez l'arrêter avec Ctrl+C. Si vous avez besoin d'une plus grande précision, vous pouvez l'utiliser pour vous donner des nanosecondes:

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

Enfin, si vous voulez vraiment un format "chronomètre", où tout commence à 0 et commence à augmenter, vous pouvez faire quelque chose comme ceci:

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

Pour un compte à rebours (qui n'est pas ce que votre question initiale demandait), vous pouvez le faire (changez les secondes en conséquence):

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

Vous pouvez les combiner en commandes simples en utilisant les fonctions bash (ou le shell de votre choix). En bash, ajoutez ces lignes à votre ~/.bashrc (la sleep 0.1 le système attendra 1 / 10ème de seconde entre chaque exécution afin de ne pas spammer votre 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
}

Vous pouvez ensuite lancer un compte à rebours d'une minute en exécutant:

countdown 60

Vous pouvez compter deux heures avec:

countdown $((2*60*60))

ou toute une journée en utilisant:

countdown $((24*60*60))

Et commencez le chronomètre en exécutant:

stopwatch

Si vous devez être capable de gérer les jours, les heures, les minutes et les secondes, vous pouvez faire quelque chose comme ceci:

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
}

Notez que le stopwatch la fonction n'a pas été testée depuis des jours car je ne voulais pas vraiment attendre 24 heures. Cela devrait fonctionner mais s'il vous plaît faites le moi savoir si ce n'est pas le cas.


159
2018-06-24 22:11



J'ai ajouté ces belles fonctions à mon .zshrc juste après avoir lu votre réponse. Aujourd'hui j'ai utilisé countdown la première fois et a remarqué une utilisation du processeur plutôt élevée. J'ai ajouté un sleep 0.1 (Je ne sais pas si un temps de sommeil d'une fraction de seconde est pris en charge sur tous les systèmes), ce qui a beaucoup amélioré la situation. L'inconvénient est bien sûr une précision d'affichage moins précise, mais je peux vivre avec une déviation de max. 100ms - mpy
@mpy merci de l'avoir mentionné. Je fais ~ 3% d'utilisation du processeur en faisant cela bash, Je peux vivre avec ça (même si est plus haut que prévu et j'ai également ajouté le sommeil à mon propre .bashrc). - terdon
@terdon: Je dois avouer que je l'ai utilisé sur une machine assez ancienne (2007 ?!) et que le CPU a augmenté de 18% ... sinon je n'aurais probablement pas remarqué. - mpy
Juste trouvé cette réponse. J'ai trouvé pratique de mettre le retour chariot au début de la commande echo dans la fonction chronomètre car cela signifiait que tuer le chronomètre n'écrasait pas la durée du chronomètre actuelle: echo -ne "\ r $ (date -u --date @ $ ((date +%s - $ date1)) +% H:% M:% S) "; - mkingston
@chishaku: Sous OS X, cela semblait fonctionner pour moi: echo -ne "$(date -ju -f %s $(($date1 - date +% s)) +%H:%M:%S)\r"; - user1071847


Ma façon préférée est la suivante:

Début:

time cat

Arrêtez:

ctrl+c

Comme @wjandrea l'a commenté ci-dessous, une autre version doit être exécutée:

time read

et appuyez sur Enter arrêter


83
2018-03-30 08:26



+1. Lifehacker a présenté cette astuce. - Nathan Arthur
similaire, mais vous pouvez appuyer sur Entrée pour l'arrêter: time read - wjandrea
time read échoue dans zsh, mais time (read) travaux. - Sparhawk
Le problème est que vous ne pouvez pas voir l'heure sans l'annuler ou la terminer. Lorsque vous le redémarrez, la minuterie recommence. - Zelphir


Je cherchais la même chose et j'ai fini par écrire quelque chose de plus élaboré en Python:

Cela vous donnera un simple compte à rebours de 10 secondes:

sudo pip install termdown
termdown 10

La source: https://github.com/trehn/termdown


28
2018-06-06 07:06



@DoktoroReichard: Eh bien, c'est un lien de téléchargement. - harrymc
ne fonctionne pas avec python 3.x - Suhaib
@Suhaib: Cela devrait et fait pour moi. S'il vous plaît, posez un problème sur GitHub avec plus d'informations. - trehn
Je l'aime - c'est juste mon allée - Wayne Werner
Très bien, j'aime bien les ASCII - Guillermo


J'ai utilisé celui-ci:

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
)

Exemple:

 countdown "00:07:55"

Voici un la source.


12
2018-06-26 19:52



Compatible POSIX - fonctionne sur OS X :) - djule5


sh-3.2# man leave

régler une minuterie pendant 15 minutes

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

edit: j'avais un tas de liens ouverts, et je pensais que c'était spécifique à osx, désolé pour ça. Laissant ma réponse pour que les autres soient au courant des congés sur les BSD.


9
2017-11-03 19:06



Leave Works in Linux aussi, mais vous devez d'abord installer le programme Leave à partir des référentiels par défaut. - karel


Ceci est pour un chronomètre avec centièmes de seconde:

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

Exemple


6
2017-12-29 05:42



Belle solution Linux uniquement! J'aime le manque d'appels externes. Notez que mon système Debian a deux valeurs dans / proc / uptime, la seconde faisant probablement référence à ma disponibilité précédente. Ce script peut être ajusté pour remédier à cela en changeant la ligne 5 en return $1 - Adam Katz


Une autre approche

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

Pour Mac:

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

Si l'on veut un signal quand il atteint zéro, on pourrait par ex. construire avec une commande qui a retourné un état de sortie non nul à zéro et le combiner avec watch -b, ou quelque chose, mais si l'on veut construire un script plus élaboré, ce n'est probablement pas la voie à suivre; il s'agit plutôt d'une solution de type "one-liner" rapide et sale.


J'aime le watch programme en général. Je l'ai d'abord vu après avoir déjà écrit d'innombrables while sleep 5; do boucles aux effets différents. watch était manifestement plus sympa.


4
2017-08-21 19:13





J'ai combiné la très bonne réponse de terdon à une fonction qui affiche simultanément le temps écoulé depuis le début et l'heure jusqu'à la fin. Il y a aussi trois variantes, donc c'est plus facile à appeler (vous n'avez pas à faire de maths bash), et il est aussi abstrait. Exemple d'utilisation:

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

Et quelque chose comme minuterie de travail:

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

Et si vous avez besoin d'un temps très précis:

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

Voici le code mettre dans votre .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]})) 
}

Combinez cela avec un moyen de jouer du son dans le terminal linux (lire des fichiers mp3 ou wav via la ligne de commande Linux) ou cygwin (cat /path/foo.wav > /dev/dsp  travaille pour moi dans babun / win7) et vous avez un Minuterie flexible simple avec alarme!


3
2018-02-01 14:42





J'ai fini par écrire mon propre 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 

3
2018-06-25 00:40



Joli script, +1. Juste pour que vous sachiez, c'est un compte à rebours, pas un chronomètre. - terdon
Tu as raison, c'est ce que je voulais vraiment. Je vais mettre à jour mon nom. - tir38


Je suis surpris que personne n'ait utilisé le sleepenh outil dans leurs scripts. Au lieu de cela, les solutions proposées utilisent soit un sleep 1 entre les sorties de temporisation suivantes ou une boucle occupée qui émet aussi rapidement que possible. Le premier est inadéquat car, en raison du peu de temps passé à faire l’impression, la sortie ne se produira pas une fois par seconde mais un peu moins que ce qui est sous-optimal. Après un temps suffisant passé, le compteur passera une seconde. Ce dernier est inadéquat car il maintient le processeur occupé sans raison valable.

L'outil que j'ai dans mon $PATH ressemble à ça:

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

Le script peut être utilisé comme chronomètre (compte à rebours jusqu'à interruption) ou comme une minuterie exécutée pendant la durée spécifiée. Depuis le sleep commande est utilisée, ce script permet de spécifier la durée pour laquelle compter dans la même précision que votre sleep permet. Sur Debian et ses dérivés, cela inclut des dortoirs inférieurs à la seconde et une manière lisible par l’homme de spécifier l’heure. Ainsi, par exemple, vous pouvez dire:

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

Et comme vous pouvez le voir, la commande a fonctionné exactement pendant 2 minutes et 4,6 secondes sans trop de magie dans le script lui-même.

MODIFIER:

L'outil sleepenh provient du paquet du même nom dans Debian et de ses dérivés comme Ubuntu. Pour les distributions qui ne l’ont pas, elle provient de https://github.com/nsc-deb/sleepenh

L'avantage de sleepenh est qu'il est capable de prendre en compte le petit retard qui s'accumule dans le temps à partir du traitement d'autres choses que le sommeil pendant une boucle. Même si on voulait juste sleep 1 dans une boucle 10 fois, l'exécution globale prendrait un peu plus de 10 secondes à cause de la petite surcharge résultant de l'exécution sleep et itérer la boucle. Cette erreur s’accumule lentement et, avec le temps, rendrait notre chronomètre de plus en plus imprécis. Pour résoudre ce problème, il faut que chaque itération de boucle calcule le temps de sommeil précis, qui est généralement légèrement inférieur à une seconde (pour les temporisateurs d'un intervalle d'une seconde). L'outil sleepenh fait cela pour vous.


3
2017-11-24 15:38



Je ne comprends pas quel avantage cela donne sur ma réponse qui utilise aussi sleep 0.1. Quel est sleepnh (Je ne peux pas le trouver dans les pensions Arch) et en quoi diffère-t-il de sleep? Pour autant que je sache, vous faites essentiellement la même chose que ma réponse ci-dessus. Qu'est-ce que je rate? - terdon
@terdon Sleepenh vient d'ici github.com/nsc-deb/sleepenh Le problème avec juste dire sleep 5 est que vous ne dormez pas pendant exactement 5 secondes. Essayez par exemple time sleep 5 et vous voyez que l'exécution de la commande prend un peu plus de 5 secondes. Au fil du temps, les erreurs s'accumulent. L'utilitaire sleepenh permet d'éviter facilement cette accumulation d'erreur. - josch
D'ACCORD. Sur mon système, je vois une erreur de 0,002 seconde. Je doute vraiment que quiconque utilise ce type d’outil et s’attende à une précision supérieure à la milliseconde, mais il serait préférable que vous modifiiez au moins votre réponse et que vous expliquiez pourquoi. sleepnh est mieux que sleep (vous dites que les autres réponses utilisent sleep 1-Ce qu'ils ne font pas, seul l'OP utilise cela) et ii) où l'obtenir et comment l'installer car ce n'est pas un outil standard. - terdon
@terdon j'ai expliqué la différence entre sleep et sleepenh dans le premier paragraphe. Quoi qu’il en soit, je n’étais probablement pas assez clair à ce sujet, alors j’en ai développé plus à la fin. Les problèmes de précision en millisecondes sont ce que vous obtenez lorsque vous appelez sleep une fois que. Ils s'accumulent avec le temps et à un moment donné, ils sont visibles. Je n'ai pas dit que les autres n'utilisent que sleep 1. J'ai dit qu'ils utilisent sleep 1 ou un busyloop. Ce qu'ils font encore Montrez-moi un contre-exemple. Réponses qui font sleep 0.1 sont les mêmes que ceux qui le font sleep 1 sauf qu'ils accumulent des erreurs encore plus rapidement. - josch
J'ai trouvé les réponses à la recherche de quelqu'un reconnaissant au moins l'existence du problème que vous avez résolu. - mariotomo