Чи є спосіб відобразити таймер зворотного відліку або секундоміра в терміналі?


144

Як я можу відобразити таймер зворотного відліку в режимі реального часу на терміналі Linux? Чи існує це додаток або, ще краще, один вкладиш для цього?

Відповіді:


184

Я не впевнений, навіщо вам потрібно beep, якщо все, що вам потрібно, - секундомір, ви можете зробити це:

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

Це покаже вам секунди, що проходять у режимі реального часу, і ви можете зупинити це за допомогою Ctrl+ C. Якщо вам потрібна більша точність, ви можете використовувати це для наносекунд:

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

Нарешті, якщо ви дуже хочете "формат секундоміра", де все починається з 0 і починає зростати, ви можете зробити щось подібне:

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

Для таймера зворотного відліку (який не запитував ваш початковий запитання) ви можете це зробити (відповідно змінити секунди):

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

Ви можете комбінувати їх у прості команди, використовуючи функції bash (або залежно від оболонки). У bash, додайте ці рядки до свого ~/.bashrc(система sleep 0.1змусить систему чекати 1/10 секунди між кожним запуском, щоб ви не спамували ваш процесор):

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
}

Потім можна запустити таймер зворотного відліку на одну хвилину, запустивши:

countdown 60

Ви можете відлічити дві години за допомогою:

countdown $((2*60*60))

або цілий день, використовуючи:

countdown $((24*60*60))

І запустіть секундомір, запустивши:

stopwatch

Якщо вам потрібно впоратися з днями, а також годинами, хвилинами та секундами, ви можете зробити щось подібне:

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
}

Зауважте, що ця stopwatchфункція не перевірялася протягом кількох днів, оскільки я не хотів її чекати 24 години. Це має працювати, але, будь ласка, повідомте мене, якщо це не так.


9
Я додав ці приємні функції .zshrcправоруч після того, як я прочитав вашу відповідь. Сьогодні я використав countdownперший раз і помітив досить високе використання процесора. Я додав sleep 0.1(не знаю, чи підтримується час сну дробовою секундою у всіх системах), що значно покращило це. Недолік - це, звичайно, менша точність відображення, але я можу жити з відхиленням макс. 100мс.
mpy

@mpy дякую, що згадуєте про це. Я отримую ~ 3% завантаження процесора при виконанні цього в bash, я можу жити з цим (хоча це більше , ніж я очікував , і я також додав сон моєї .bashrc).
тердон

3
Щойно знайшов цю відповідь. Я виявив, що введення повернення каретки на початку заяви про ехо у функції секундоміра було зручним, оскільки це означало, що вбивство секундоміра не перезаписало поточний час секундоміра: echo -ne "\ r $ (дата -u - дата @ $ (( date +%s- $ date1)) +% H:% M:% S) ";
mkingston

3
@chishaku: На OS X це, здавалося, працює для мене: echo -ne "$(date -ju -f %s $(($date1 - дата +% s )) +%H:%M:%S)\r";
користувач1071847

1
З пакетом Сокс Я хотів би додати хороший звук , щоб грати в кінці зворотного відліку: play -q -n synth 2 pluck C5.
Пабло А

94

Мій улюблений спосіб:

Початок:

time cat

Стій:

ctrl+c

Як @wjandrea прокоментував нижче, запускається інша версія:

time read

і натисніть, Enterщоб зупинити



8
подібне, але ви можете натиснути Enter, щоб зупинити його:time read
wjandrea

10
time readне в zsh, але time (read)працює.
Спархаук

Однак проблема полягає в тому, що ви не можете бачити час, не скасовуючи його або закінчуючи. Після цього перезапустіть таймер заново.
Зельфір Кальтшталь

39

Я шукав те саме і закінчив написати щось більш досконале в Python:

Це дасть вам простий 10-секундний відлік:

sudo pip install termdown
termdown 10

Джерело: https://github.com/trehn/termdown


1
@DoktoroReichard: Ну, це посилання для завантаження.
harrymc

1
@Suhaib: Це повинно робити для мене. Будь-ласка, поставте питання на GitHub, щоб отримати більше інформації.
trehn

1
Мені подобається - це прямо моя алея
Уейн Вернер

1
Дуже приємно, мені подобається ASCII
Гільєрмо

1
Це дійсно круто! 😄
orschiro

13

Я користувався цим:

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
)

Приклад:

 countdown "00:07:55"

Ось джерело .


2
POSIX сумісний - працює на OS X :)
djule5

13
sh-3.2# man leave

встановити таймер на 15 хвилин

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

редагувати: У мене було відкрито купу посилань, і я подумав, що це стосується osx, вибачте з цього приводу. Залишаючи свою відповідь, щоб інші знали про відпустку в BSD.


1
також працює в Linux, але спочатку потрібно встановити програму виходу із сховищ за замовчуванням.
карел

6

Це для секундоміра з часткою секунди:

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

Приклад


Приємне рішення лише для Linux! Мені подобається відсутність зовнішніх дзвінків. Зауважте, моя система Debian має два значення в / proc / uptime, причому друге, мабуть, стосується мого попереднього часу безперервного часу. Цей сценарій можна скорегувати, щоб виправити це, змінивши лінію 5 наreturn $1
Адам Кац

4

Я поєднав дуже гарну відповідь тердона, у функцію, яка одночасно відображає час від початку і час до кінця. Існує також три варіанти, тому їх простіше зателефонувати (вам не потрібно займатися математикою), і це також абстрагується. Приклад використання :

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

І щось на кшталт робочого таймера:

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

А якщо вам потрібен дуже конкретний час:

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

Ось код, який потрібно ввести у свій .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]})) 
}

Поєднайте це з деяким способом відтворення звуку в Linux-терміналі ( відтворюйте mp3 або WAV-файл через командний рядок Linux ) або cygwin ( cat /path/foo.wav > /dev/dsp працює для мене в babun / win7), і у вас є простий гнучкий таймер із сигналізацією !


4

Ще один підхід

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

Для Mac:

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

Якщо хтось хоче, щоб сигнал, коли він потрапляє на нуль, можна, наприклад, створити його за допомогою команди, яка повернула ненульовий статус виходу в нуль і поєднати його з watch -bчи іншим, але якщо хочеться створити більш досконалий сценарій, це, ймовірно, не шлях; це скоріше рішення типу "швидкий і брудний однолінійний".


Мені подобається watchпрограма взагалі. Я вперше побачив це після того, як я вже написав незліченну кількість while sleep 5; doциклів для різних ефектів. watchбуло демонстративно приємніше.


3

Я закінчив писати власний сценарій оболонки: 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 

1
Гарний сценарій, +1. Просто ви знаєте, що це таймер зворотного відліку, а не секундомір.
тердон

га ти маєш рацію, ось чого я дуже хотів. Я оновлю свою назву.
tir38

3

Я здивований, що ніхто не використовував sleepenhінструмент у своїх сценаріях. Натомість запропоновані рішення або використовують sleep 1між наступними виходами таймера або зайнятим циклом, який виводиться якомога швидше. Перший є неадекватним, оскільки через малий час, витрачений на друк, вихід насправді не відбудеться раз на секунду, але трохи менше, ніж той, який є неоптимальним. Після того, як пройшло достатньо часу, лічильник пропустить секунду. Останнє є неадекватним, тому що воно не заважає процесору займатися.

Інструмент, який у мене є, $PATHвиглядає так:

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

Сценарій може бути використаний як секундомір (підрахунок до переривання) або як таймер, який працює протягом визначеного часу. Оскільки sleepкоманда використовується, цей скрипт дозволяє вказати тривалість, за яку слід рахувати в тій же точності, що sleepдозволяє. Що стосується Debian та похідних програм, це включає час другого режиму сну та приємний для людини спосіб ознайомлення із зазначенням часу. Так, наприклад, ви можете сказати:

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

І як бачите, команда виконувала рівно 2 хвилини та 4,6 секунди без особливої ​​магії у самому сценарії.

Редагувати :

Інструмент Slepenh походить від однойменного пакету в Debian та його похідних, таких як Ubuntu. Для дистрибутивів, у яких його немає, він надходить з https://github.com/nsc-deb/sleepenh

Перевага дрімоти полягає в тому, що він здатний враховувати малу затримку, яка накопичується з часом від обробки інших речей, ніж сну під час циклу. Навіть якби ви sleep 1потрапляли в цикл 10 разів, загальне виконання зайняло б трохи більше 10 секунд через невеликі накладні витрати, які виникають від виконання sleepта повторення циклу. Ця помилка повільно накопичується і з часом зробить наш таймер секундоміра все більш неточним. Щоб вирішити цю проблему, необхідно для кожної ітерації циклу обчислити точний час для сну, який зазвичай трохи менше секунди (на таймери інтервалу на одну секунду). Інструмент сонник робить це за вас.


Я не розумію, яку вигоду це дає від моєї відповіді, яка також використовує sleep 0.1. Що таке sleepnh(я не можу знайти його в Arch repos) і чим він відрізняється від sleep? Наскільки я можу сказати, ви в основному робите те саме, що моя відповідь вище. Що я пропускаю?
тердон

@terdon Sleepenh походить звідси github.com/nsc-deb/sleepenh Проблема просто сказати sleep 5, що ти не спиш рівно 5 секунд. Спробуйте, наприклад, time sleep 5і ви бачите, що виконання команди займає трохи більше 5 секунд. З часом помилки накопичуються. Утиліта Slepenh дозволяє легко уникнути цього накопичення помилок.
Джош

ГАРАЗД. У моїй системі я бачу помилку 0,002 секунди. Я дійсно сумніваюся, що хтось скористався б таким інструментом і очікував би кращої за мілісекундну точність, але було б краще, якби ви принаймні відредагували свою відповідь, і я пояснив, чому sleepnhце краще, ніж sleepви (ви говорите лише, що інші відповіді використовують sleep 1- чого вони не роблять) , тільки ОП використовує це) та ii) де його отримати та як встановити, оскільки це не стандартний інструмент.
тердон

1
@terdon Я пояснив різницю між першим пунктом sleepта sleepenhв ньому. У всякому разі, я, мабуть, не був досить зрозумілий у цьому, тому в кінці кінців розширив більше. Проблеми з точністю до мілісекунд - це те, що ви отримуєте, коли дзвоните sleepодин раз. Вони накопичуються з часом, і в якийсь момент це помітно. Я не сказав, що інші використовують лише sleep 1. Я сказав, що вони використовують sleep 1або зайняту петлю. Що вони ще роблять. Покажіть мені зустрічний приклад. Відповіді, які sleep 0.1є, такі ж, як і у тих, хто робить, sleep 1за винятком того, що вони накопичують помилки ще швидше.
Джош

Я дійшов відповідей, шукаючи когось, принаймні, визнаючи існування проблеми, яку ви вирішили.
mariotomo

2

Коротка відповідь:

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

Пояснення:

Я знаю, що відповідей дуже багато, але я просто хочу опублікувати щось дуже близьке до питання ОП, яке особисто я би сприйняв як " справді зворотний відлік в лінійці ". Мої цілі:

  1. Один лайнер.
  2. Відлік часу.
  3. Легко запам’ятати та набрати в консолі (без функцій та важкої логіки, лише башти).
  4. Не вимагає додаткового програмного забезпечення для встановлення (можна використовувати на будь-якому сервері, на якому я переходжу через ssh, навіть якщо у мене немає кореня).

Як це працює:

  1. seq друкує числа від 60 до 1.
  2. echo -ne "\r$i "повертає каре до початку рядка і друкує поточне $iзначення. Пробіл після нього потрібно замінити попереднім значенням, якщо воно було довше символів, ніж поточне $i(10 -> 9).

1
Це найкраще спрацювало в моєму випадку використання на Mac OS для використання в скрипті bash. Пояснення, як це працює, є надзвичайно корисним.
Джеймс Кемпбелл

1

Для подальшого ознайомлення існує інструмент командного рядка під назвою µTimer з дуже простими параметрами командного рядка для таймера зворотного відліку / відліку.


1

Притворіться, що ви людина в OSX, яка шукає секундомір командного рядка. Притворіться, що ви не хочете встановлювати інструменти gnu і просто хочете запустити з Unixdate

у такому випадку зробіть так, як говорить @terdon, але з цією модифікацією:

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
Я спробував це на OS X El Capitan, чомусь це починається з 16:00:00
nopole

1

Просто використовуйте годинник + дата в UTC час. Ви також можете встановити якийсь пакет для великого відображення ...

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'

Спробуй це!

Дивіться також http://www.cyberciti.biz/faq/create-large-colorful-text-banner-on-screen/


1

sw - простий секундомір, який працюватиме назавжди.

sw

Встановити

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

1

Приклад пітона:

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

демонстрація


1

Погляньте на TermTime , це приємний годинник та секундомір на базі терміналу:

pip install termtime


0

Це схоже на прийняту відповідь, але тердон countdown()дав мені синтаксичні помилки. Цей для мене чудово працює:

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

Ви можете помістити його .bashrcта виконати за допомогою: timer t(де t - час у хвилинах).


0

Знайшли це питання раніше сьогодні, коли шукали термінову програму для відображення великого таймера зворотного відліку для семінару. Жодна з пропозицій не була саме такою, що мені потрібна, тому я швидко зібрав ще одну в Go: https://github.com/bnaucler/cdown

Оскільки на питання вже достатньо відповіді, вважайте це заради нащадків.


0

$ сон 1500 && xterm -fg жовтий -g 240x80 &

Коли той великий термінал з жовтим текстом підскакує, час вставати і розтягуватися!

Примітки: - 1500 секунд = 25 хвилин помдоро - 240х80 = розмір терміналу з 240 символьними рядами та 80 рядками. Помітно заповнює екран.

Кредит: http://www.linuxquestions.org/questions/linux-newbie-8/countdown-timer-for-linux-949463/


0

Версія GUI секундоміра

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

-2

Якщо ви хочете, щоб програма з компіляції з будь-якої причини була б наступною:

#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;
}

Це можна використовувати в інших програмах, а також легко переноситься, якщо bash середовище недоступне або ви просто бажаєте використовувати компільовану програму

github

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.