Вопрос: Есть ли способ отображения таймера обратного отсчета или секундомера в терминале?


Как я могу отображать таймер обратного отсчета в реальном времени на терминале Linux? Есть ли существующее приложение или, что еще лучше, один лайнер для этого?


122
2018-06-24 20:13


Источник


относительно SU hold: Я думаю, что это подпадает под «компьютерное программное обеспечение» без «запроса рекомендации по покупке или продукту». Я не прошу рекомендаций; Я спрашиваю, существует ли что-то. Когда я изначально задал вопрос, я ожидал, может быть, «да, это встроенный скрипт -nix». Если я смогу реструктурировать вопрос, я это сделаю. - tir38
Это то, что я пытался сделать. Это касается темы после моего редактирования, насколько мне известно, и я проголосовал за ее повторное открытие. - terdon
@terdon спасибо, я вижу, как это лучший вопрос. - tir38


Ответы:


Я не уверен, зачем вам нужно beep, если все, что вы хотите, это секундомер, вы можете сделать это:

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

Это покажет вам секунды, проходящие в реальном времени, и вы можете остановить их с помощью Ctrl+С, Если вам нужна большая точность, вы можете использовать это, чтобы дать вам наносекунды:

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 часа. Он должен работать, но, пожалуйста, дайте мне знать, если это не так.


158
2018-06-24 22:11



Я добавил эти приятные функции к моему .zshrc сразу после того, как я прочитал ваш ответ. Сегодня я использовал countdown в первый раз и заметил довольно высокий уровень использования ЦП. Я добавил sleep 0.1 (Я не знаю, поддерживается ли время сна дробной секунды во всех системах), что значительно улучшило его. Недостатком является, конечно, менее точная точность отображения, но я могу жить с отклонением макс. 100мс. - mpy
@mpy благодарит за это. Я получаю ~ 3% использования ЦП при выполнении этого в bash, Я могу жить с этим (хотя это является выше, чем я ожидал, и я также добавил сон на свой собственный .bashrc). - terdon
@terdon: Должен признаться, что использовал его на довольно старой машине (2007!), а CPU вырос до 18% ... иначе я бы, наверное, не заметил. - mpy
Просто нашел этот ответ. Я нашел, что перенос каретки в начале выражения эха в функции секундомера был удобен, так как это означало, что убийство секундомера не перезаписало текущее время секундомера: echo -ne "\ r $ (date -u -date @ $ ((date +%s - $ date1)) +% H:% M:% S) "; - mkingston
@chishaku: В OS X это показалось мне полезным: echo -ne "$(date -ju -f %s $(($date1 - date +% s)) +%H:%M:%S)\r"; - user1071847


Мой любимый способ:

Начало:

time cat

Стоп:

ctrl+c

Как пояснил @wjandrea ниже, другая версия должна запускаться:

time read

и нажмите Enter остановиться


83
2018-03-30 08:26



+1. Lifehacker показал этот трюк. - Nathan Arthur
аналогично, но вы можете нажать Enter, чтобы остановить его: time read - wjandrea
time read сбой в zsh, но time (read) работает. - Sparhawk
Проблема в том, что вы не можете видеть время, не отменяя его или не заканчивая. Когда вы его перезагрузите, таймер начнет заново. - Zelphir


Я искал то же самое и в итоге написал что-то более сложное в Python:

Это даст вам простой 10-секундный обратный отсчет:

sudo pip install termdown
termdown 10

Источник: https://github.com/trehn/termdown


28
2018-06-06 07:06



@DoktoroReichard: Ну, это ссылка для скачивания. - harrymc
не работает с python 3.x - Suhaib
@ Суаиб: Это должно и для меня. Пожалуйста, поднимите вопрос о GitHub с дополнительной информацией. - trehn
Мне это нравится - это прямо вверх по моей аллее - Wayne Werner
Очень приятно, мне нравится ASCII - Guillermo


Я использовал этот:

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"

Вот источник,


12
2018-06-26 19:52



POSIX совместимый - работает на OS X :) - djule5


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#

edit: У меня была связка ссылок, и я подумал, что это характерно для osx, извините за это. Оставляя мой ответ, чтобы другие знали о выходе на BSD.


9
2017-11-03 19:06



также оставляйте работы в Linux, но сначала вам нужно установить программу отпуска из репозиториев по умолчанию. - karel


Это для секундомера с сотой секунды:

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

пример


6
2017-12-29 05:42



Хорошее решение для Linux! Мне нравится отсутствие внешних звонков. Обратите внимание: моя система Debian имеет два значения в / proc / uptime, а вторая, по-видимому, относится к моему предыдущему времени безотказной работы. Этот скрипт можно настроить таким образом, чтобы исправить это, изменив строку 5 на return $1 - Adam Katz


Другой подход

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 было явно лучше.


4
2017-08-21 19:13





Я объединил очень хороший ответ тердона, в функцию, которая в то же время отображает время с начала, и время до конца. Есть также три варианта, поэтому их легче назвать (вам не нужно делать bash math), и это также абстрагируется. Пример использования:

{ ~ }  » 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  работает для меня в бабуни / win7), и у вас есть простой гибкий таймер с сигнализацией!


3
2018-02-01 14:42





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



Хороший сценарий, +1. Просто чтобы вы знали, это таймер обратного отсчета, а не секундомер. - terdon
га, ты прав, вот чего я действительно хотел. Я обновлю свое имя. - tir38


Я удивлен, что никто не использовал sleepenh инструмент в их скриптах. Вместо этого предлагаемые решения либо используют sleep 1 между последующими выходами таймера или циклом занятости, который выводится как можно быстрее. Первый из них неадекватен, поскольку из-за небольшого времени, затраченного на печать, вывод не будет происходить раз в секунду, а немного меньше, чем тот, который является субоптимальным. По прошествии достаточно времени счетчик пропустит секунду. Последнее неадекватно, потому что он не позволяет загружать CPU без уважительной причины.

Инструмент, который у меня есть в моем $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 секунды без магии в самом скрипте.

РЕДАКТИРОВАТЬ:

Инструмент sleepenh происходит из пакета с тем же именем в Debian и его производных, таких как Ubuntu. Для дистрибутивов, которые его не имеют, это происходит из https://github.com/nsc-deb/sleepenh

Преимущество sleepenh заключается в том, что он способен учитывать небольшую задержку, которая накапливается во времени от обработки других вещей, кроме сна во время цикла. Даже если бы просто sleep 1 в цикле 10 раз общее выполнение займет немного больше 10 секунд из-за небольших накладных расходов, которые исходят от выполнения sleep и итерации цикла. Эта ошибка медленно накапливается и со временем сделает наш таймер секундомера все более и более неточным. Чтобы исправить эту проблему, необходимо, чтобы каждая итерация цикла вычисляла точное время сна, которое обычно немного меньше секунды (для таймеров с одной секундой). Инструмент sleepenh делает это за вас.


3
2017-11-24 15:38



Я не понимаю, какая польза от этого дает мой ответ, который также использует sleep 0.1, Что sleepnh (Я не могу найти его в репозиториях Arch) и как он отличается от sleep? Насколько я могу судить, вы в основном делаете то же, что и мой ответ выше. Что мне не хватает? - terdon
@terdon Sleepenh приходит отсюда github.com/nsc-deb/sleepenh Проблема с просто высказыванием sleep 5 что вы не спите ровно 5 секунд. Попробуйте, например time sleep 5 и вы видите, что выполнение команды занимает чуть больше 5 секунд. Со временем ошибки накапливаются. Утилита sleepenh позволяет легко избежать этого накопления ошибок. - josch
ОК. В моей системе я вижу ошибку 0,002 секунды. Я действительно сомневаюсь, что кто-нибудь будет использовать этот инструмент и ожидать лучше, чем миллисекундную точность, но было бы лучше, если бы вы хотя бы отредактировали свой ответ, и я объясню, почему sleepnh Это лучше чем sleep (вы только говорите, что используют другие ответы sleep 1-Что они этого не делают, только OP использует это), и ii) где его получить и как его установить, поскольку он не является стандартным инструментом. - terdon
@terdon Я объяснил разницу между sleep а также sleepenh в первом абзаце. В любом случае, я, вероятно, не был достаточно ясен, поэтому я больше расширил его в конце. Проблемы с точностью до миллисекунды - это то, что вы получаете при вызове sleep один раз. Они накапливаются со временем, и в какой-то момент это примечательно. Я не говорил, что другие используют только sleep 1, Я сказал, что они используют sleep 1 или занят. Что они все еще делают. Покажите мне счетчик. Ответы, которые делают sleep 0.1 те же, что и sleep 1 за исключением того, что они накапливают ошибки еще быстрее. - josch
Я пришел к ответам, ища кого-то, по крайней мере, признающего существование проблемы, которую вы решили. - mariotomo


Для дальнейшего использования имеется инструмент командной строки, называемый μTimer с очень простыми параметрами командной строки для таймера обратного отсчета / подсчета.


1
2017-09-26 15:21