2013-06-24 20:13:51 +0000 2013-06-24 20:13:51 +0000
157
157

Есть ли способ отобразить обратный отсчет или таймер секундомера в терминале?

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

Ответы (22)

195
195
195
2013-06-24 22:11:13 +0000

Я не уверен, зачем тебе нужен секундомер 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

Для таймера обратного отсчета (который не является тем, что ваш оригинальный вопрос был задан) вы могли бы сделать это (изменить секунды соответственно):


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

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

Вы можете запустить таймер обратного отсчета одной минуты, запустив:

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

100
100
100
2015-03-30 08:26:08 +0000

Мой любимый способ: 0x2 и 0x2 и Старт:

time cat

Стоп:

ctrl+c

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

time read

и нажмите Enter, чтобы остановиться.

46
46
46
2014-06-06 07:06:57 +0000

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

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

sudo pip install termdown
termdown 10

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

14
14
14
2016-11-03 19:06:37 +0000
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.

13
13
13
2013-06-26 19:52:03 +0000

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

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"

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

6
6
6
2013-12-29 05:42:56 +0000

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

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

Пример

5
5
5
2019-06-05 10:48:15 +0000

Короткий ответ:

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

Пояснения: 0x2 и 0x2 и я знаю, что есть много ответов, но я просто хочу разместить что-то очень близкое к вопросу ОП, что лично я бы принял как действительно “Онлайн-обратный отсчет в терминале”. Моими целями были:

  1. Один лайнер.
  2. Обратный отсчёт.
  3. Легко запоминается и вводится в консоль (без функций и тяжелой логики, только бэш).
  4. Не требует установки дополнительного программного обеспечения (может использоваться на любом сервере, через который я иду через ssh, даже если у меня нет root там).

Как это работает:

  1. seq печатает числа от 60 до 1.
  2. echo -ne "\r$i " возвращает caret к началу строки и печатает текущее значение $i. Пробел после того, как требуется перезаписать предыдущее значение, если оно было длиннее на символы, чем текущее $i (10 -> 9).
4
4
4
2015-02-01 14:42:54 +0000

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

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

3
3
3
2013-06-25 00:40:38 +0000

В итоге я написал свой собственный сценарий оболочки: 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
3
3
2016-11-24 15:38:57 +0000

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

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

EDIT :

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

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

3
3
3
2014-08-21 19:13:05 +0000

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

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

For 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
3
3
2017-06-23 21:06:54 +0000

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
1
1
2015-04-13 12:34:57 +0000

Представьте, что вы человек на OSX, который ищет секундомер из командной строки. Притворитесь, что не хотите устанавливать инструменты gnu, а просто хотите работать с unix 0x6 и 0x2 и , в этом случае делайте то, что говорит @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
1
1
2019-04-13 14:58:34 +0000

Взгляните на TermTime , это хорошие часы и секундомер на базе терминала:

pip install termtime

1
1
1
2015-06-02 01:12:11 +0000

Просто используйте часы + дата в 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
1
1
2014-09-26 15:21:48 +0000

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

1
1
1
2014-02-13 12:00:38 +0000

Пример с питоном:

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

0
0
0
2018-11-05 13:49:26 +0000

Версия графического интерфейса секундомера

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
0
0
2016-12-08 20:20:14 +0000

Нашел этот вопрос ранее сегодня, при поиске термина приложение для отображения большого таймера обратного отсчета для семинара. Ни одно из предложений не было именно тем, что мне нужно, поэтому я быстро собрал еще одно в Go: https://github.com/bnaucler/cdown

Так как на этот вопрос уже дано достаточное количество ответов, считайте, что это ради потомства.

0
0
0
2017-01-24 23:04:07 +0000

$ сна 1500 & & xterm -fg желтый -g 240x80 & 0x2 & 0x2 & Когда большой терминал с желтым текстом подпрыгивает, время, чтобы встать и растянуть!

Заметки: - 1500 секунд = 25 минут pomodoro - 240x80 = размер терминала с 240-символьными строками и 80 строками. Заметно заполняет экран.

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

0
0
0
2016-04-20 15:14:05 +0000

Это похоже на принятый ответ, но Тердон 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 - время в минутах).

-2
-2
-2
2014-08-18 17:19:37 +0000

Если по какой-то причине вам понадобится компилируемая программа, то сработает следующее:

#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 << "0x1&33[2A0x1&33[K";
    std::this_thread::sleep_for(milliseconds(100));
  }
  std::cout << "Finished" << std::endl;
  return 0;
}

Это может быть использовано и в других программах и легко переносится, если bash-окружение недоступно или вы просто предпочитаете использовать скомпилированную программу github

Похожие вопросы

6
10
7
5
11