Ответы:
Я не уверен, зачем вам 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 часа. Это должно работать, но, пожалуйста, дайте мне знать, если это не так.
bash
, я могу жить с этим (хотя это больше , чем я ожидал , и я также добавил сон моей .bashrc).
date +%s
- $ date1)) +% H:% M:% S) ";
echo -ne "$(date -ju -f %s $(($date1 -
date +% s )) +%H:%M:%S)\r"
;
play -q -n synth 2 pluck C5
.
Мой любимый способ это:
Начало:
time cat
Стоп:
ctrl+c
Как прокомментировал @wjandrea ниже, запускается еще одна версия:
time read
и нажмите, Enter
чтобы остановить
time read
time read
терпит неудачу в zsh, но time (read)
работает.
Я искал то же самое и закончил тем, что написал что-то более сложное в Python:
Это даст вам простой 10-секундный отсчет:
sudo pip install termdown
termdown 10
Источник: https://github.com/trehn/termdown.
Я использовал это:
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"
Вот источник .
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.
Это для секундомера с сотыми долями секунды:
#!/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
}
}
return $1
Я объединил очень хороший ответ Тердона в функцию, которая одновременно отображает время с начала и время до конца. Есть также три варианта, так что проще звонить (вам не нужно заниматься 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
работает для меня в babun / win7), и у вас есть простой гибкий таймер с будильником !
Другой подход
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
было явно лучше.
В итоге я написал свой собственный скрипт: 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
Я удивлен, что никто не использовал этот 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 секунды без особой магии в самом скрипте.
РЕДАКТИРОВАТЬ :
Инструмент sleepenh происходит из одноименного пакета в Debian и его производных, таких как Ubuntu. Для дистрибутивов, у которых его нет, он приходит по адресу https://github.com/nsc-deb/sleepenh.
Преимущество sleepenh заключается в том, что он способен учитывать небольшую задержку, которая накапливается со временем при обработке других вещей, кроме сна во время цикла. Даже если один sleep 1
цикл будет выполнен 10 раз, общее выполнение займет чуть больше 10 секунд из-за небольших накладных расходов, возникающих при выполнении sleep
и повторении цикла. Эта ошибка медленно накапливается и со временем сделает наш секундомер все более и более неточным. Чтобы решить эту проблему, необходимо, чтобы каждая итерация цикла вычисляла точное время ожидания, которое обычно немного меньше секунды (для таймеров с интервалом в одну секунду). Инструмент Sleepenh делает это для вас.
sleep 0.1
. Что такое sleepnh
(я не могу найти его в репозиториях Arch) и чем оно отличается sleep
? Насколько я могу судить, вы делаете то же самое, что и мой ответ выше. Что мне не хватает?
sleep 5
, чтобы просто сказать , что вы не спите ровно 5 секунд. Попробуйте, например, time sleep 5
и вы увидите, что выполнение команды занимает чуть более 5 секунд. Со временем ошибки накапливаются. Утилита sleepenh позволяет легко избежать накопления ошибок.
sleepnh
это лучше, чем sleep
(вы говорите, что другие ответы используют - а sleep 1
они этого не делают). , только OP использует это) и ii) где его взять и как установить, так как это не стандартный инструмент.
sleep
и sleepenh
в первом абзаце. В любом случае, я, вероятно, не был достаточно ясен в этом вопросе, поэтому я остановился на этом подробнее. Проблемы с точностью до миллисекунды - это то, что вы получаете, когда звоните sleep
один раз. Они накапливаются со временем, и в какой-то момент это заметно. Я не сказал, что другие используют только sleep 1
. Я сказал, что они используют sleep 1
или busyloop. Что они до сих пор делают. Покажите мне встречный пример. Ответы sleep 0.1
такие же, как и ответы, sleep 1
за исключением того, что они накапливают ошибки еще быстрее.
Краткий ответ:
for i in `seq 60 -1 1` ; do echo -ne "\r$i " ; sleep 1 ; done
Объяснение:
Я знаю, что есть много ответов, но я просто хочу опубликовать что-то очень близкое к вопросу ОП, которое лично я бы принял как « обратный отсчет в терминале ». Моими целями были:
Как это устроено:
seq
печатает номера от 60 до 1.echo -ne "\r$i "
возвращает курсор в начало строки и печатает текущее $i
значение. Пробел после него требуется перезаписать предыдущее значение, если оно было длиннее символов, чем текущее $i
(10 -> 9).Представьте, что вы человек в 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
}
Просто используйте часы + дата в 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/
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
Пример 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()
Это похоже на принятый ответ, но тердон 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 - время в минутах).
Нашел этот вопрос ранее сегодня, когда искал термин приложение для отображения большого таймера обратного отсчета для семинара. Ни одно из предложений не было именно тем, что мне было нужно, поэтому я быстро собрал другое в Go: https://github.com/bnaucler/cdown
Поскольку на этот вопрос уже дан достаточный ответ, считайте, что это ради потомков.
$ сон 1500 && xterm -fg желтый -g 240x80 &
Когда этот большой терминал с желтым текстом подпрыгнет, пора вставать и тянуться!
Примечания: - 1500 секунд = 25-минутный pomodoro - 240x80 = размер терминала с 240 символами и 80 строками. Заполняет экран для меня заметно.
Предоставлено: http://www.linuxquestions.org/questions/linux-newbie-8/countdown-timer-for-linux-949463/.
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
Если по какой-либо причине вам нужна компилируемая программа, сработает следующее:
#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 недоступна или вы просто предпочитаете использовать скомпилированную программу
.zshrc
сразу после прочтения вашего ответа. Сегодня я использовалcountdown
первый раз и заметил довольно высокую загрузку процессора. Я добавилsleep 0.1
(я не знаю, поддерживается ли время ожидания доли секунды во всех системах), что значительно улучшило это. Недостатком является, конечно, менее точная точность отображения, но я могу жить с отклонением макс. 100мс.