web-dev-qa-db-fra.com

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

Comment puis-je afficher un compte à rebours en temps réel sur le terminal Linux? Existe-t-il une application existante ou, mieux encore, une seule ligne pour le faire?

134
tir38

Je ne sais pas pourquoi vous avez besoin de beep, si tout ce que vous voulez, c'est un chronomètre, vous pouvez le faire:

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

Cela va vous montrer les secondes qui passent 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, "format chronomètre", où tout commence à 0 et commence à croître, 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 (ce qui n'est pas ce que votre question initiale vous demandait), vous pouvez le faire (changer 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). Sous bash, ajoutez ces lignes à votre ~/.bashrc (le sleep 0.1 fera attendre le système pendant 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 démarrer un compte à rebours d’une minute en exécutant:

countdown 60

Vous pouvez compter deux heures avec:

countdown $((2*60*60))

ou une journée entière en utilisant:

countdown $((24*60*60))

Et démarrez le chronomètre en lançant:

stopwatch

Si vous devez gérer des jours, des heures, des minutes et des secondes, vous pouvez procéder comme suit:

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 la fonction stopwatch 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 laissez-moi savoir si ce n'est pas le cas.

176
terdon

Ma manière préférée est:

Début:

time cat

Arrêtez:

ctrl+c

Comme @wjandrea a commenté ci-dessous, une autre version est à exécuter:

time read

et appuyez sur Enter pour arrêter

87
alfasin

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

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

Sudo pip install termdown
termdown 10

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

33
trehn
sh-3.2# man leave

régler une minuterie pour 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 en suspens pour que les autres personnes soient au courant des congés accordés aux BSD.

13
efk

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 source .

13
Adobe

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
Steven Penny

J'ai combiné la réponse du très bon terdon à une fonction qui affiche en même temps le temps écoulé depuis le début et le temps jusqu'à la fin. Il existe également trois variantes, ce qui facilite l'appel (il n'est pas nécessaire de faire des calculs élémentaires), et il est également 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 de temps très spécifique:

{ ~ }  » 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 un terminal linux ( lire un fichier mp3 ou wav via la ligne de commande Linux ) ou cygwin (cat /path/foo.wav > /dev/dsp fonctionne pour moi dans babun/win7) et vous obtenez un simple minuterie flexible avec alarme !

4
Koshmaar

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 on veut un signal quand il atteint zéro, on pourrait par exemple construisez-le avec une commande qui retourne à zéro un statut de sortie non nul et combinez-le avec watch -b, ou quelque chose du genre, mais si vous voulez construire un script plus élaboré, ce n'est probablement pas la voie à suivre; il s’agit plus d’une solution de type "one-liner" rapide et sale.


J'aime le programme watch en général. Je l'ai vu pour la première fois après avoir déjà écrit d'innombrables boucles while sleep 5; do à différents effets. watch était manifestement plus agréable.

4
Daniel Andersson

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
tir38

Je suis surpris que personne n'ait utilisé l'outil sleepenh dans leurs scripts. Au lieu de cela, les solutions proposées utilisent soit un sleep 1 entre les sorties de minuterie suivantes, soit une boucle occupée produisant le plus rapidement possible. La première solution est inadéquate car, en raison du peu de temps passé à l’impression, la sortie ne se produira pas une fois par seconde, mais un peu moins que ce qui est sous-optimal. Une fois le temps écoulé, 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 à ceci:

#!/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 (en comptant jusqu'à l'interruption) ou comme une minuterie qui s'exécute pendant la durée spécifiée. Puisque la commande sleep est utilisée, ce script permet de spécifier la durée à compter avec la même précision que votre sleep permet. Sur Debian et ses dérivés, cela inclut les temps de sommeil inférieurs à une seconde et un moyen lisible pour l’utilisateur de Nice 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 constater, la commande a fonctionné exactement pendant 2 minutes et 4,6 secondes sans trop de magie dans le script lui-même.

EDIT:

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, cela vient de https://github.com/nsc-deb/sleepenh

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

3
josch

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

 demo

1
user84207

Pour référence future, il existe un outil de ligne de commande appelé µTimer avec des options de ligne de commande très simples pour un compte à rebours/compte à rebours.

1
Tom

sw est un chronomètre simple qui fonctionnera pour toujours.

sw

Installer

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

Usage

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
1
Cory Klein

Imaginez que vous êtes une personne sur OSX à la recherche d'un chronomètre en ligne de commande. Imaginez que vous ne voulez pas installer les outils GNU et que vous voulez simplement vous lancer avec la variable unix date

dans ce cas, faites comme @terdon mais avec cette modification:

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
joem

Utilisez simplement watch + date en heure UTC. Vous pouvez également installer un paquet pour le grand affichage ...

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'

Essayez le!

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

1
MUY Belgium

Ceci est similaire à la réponse acceptée, mais les erreurs de syntaxe countdown() de terdon m'ont été envoyées. Celui-ci fonctionne bien pour moi, cependant:

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

Vous pouvez le mettre dans .bashrc et ensuite l'exécuter avec: timer t (où t est le temps en minutes).

0
Andy Forceno

Une version graphique du chronomètre

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
Mohamed Samy

Vous avez trouvé cette question plus tôt dans la journée lorsque vous recherchez une application à terme pour afficher un compte à rebours important pour un atelier. Aucune des suggestions n’étant exactement ce dont j'avais besoin, j’en ai donc rapidement créé une autre dans Go: https://github.com/bnaucler/cdown

Comme la question a déjà reçu une réponse suffisante, considérez cela comme une question de postérité.

0
B Nauclér

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

Quand ce gros terminal avec du texte jaune saute, il est temps de se lever et de s'étirer!

Remarques: - 1500 secondes = 25 minutes de pomodoro - 240x80 = taille du terminal avec 240 lignes de caractères et 80 lignes. Remplit un écran pour moi sensiblement.

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

0
user79878