Відповіді:
Я не впевнений, навіщо вам потрібно 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 -
дата +% 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
Я поєднав дуже гарну відповідь тердона, у функцію, яка одночасно відображає час від початку і час до кінця. Існує також три варіанти, тому їх простіше зателефонувати (вам не потрібно займатися математикою), і це також абстрагується. Приклад використання :
{ ~ } » 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 секунди без особливої магії у самому сценарії.
Редагувати :
Інструмент Slepenh походить від однойменного пакету в Debian та його похідних, таких як Ubuntu. Для дистрибутивів, у яких його немає, він надходить з https://github.com/nsc-deb/sleepenh
Перевага дрімоти полягає в тому, що він здатний враховувати малу затримку, яка накопичується з часом від обробки інших речей, ніж сну під час циклу. Навіть якби ви sleep 1
потрапляли в цикл 10 разів, загальне виконання зайняло б трохи більше 10 секунд через невеликі накладні витрати, які виникають від виконання sleep
та повторення циклу. Ця помилка повільно накопичується і з часом зробить наш таймер секундоміра все більш неточним. Щоб вирішити цю проблему, необхідно для кожної ітерації циклу обчислити точний час для сну, який зазвичай трохи менше секунди (на таймери інтервалу на одну секунду). Інструмент сонник робить це за вас.
sleep 0.1
. Що таке sleepnh
(я не можу знайти його в Arch repos) і чим він відрізняється від sleep
? Наскільки я можу сказати, ви в основному робите те саме, що моя відповідь вище. Що я пропускаю?
sleep 5
, що ти не спиш рівно 5 секунд. Спробуйте, наприклад, time sleep 5
і ви бачите, що виконання команди займає трохи більше 5 секунд. З часом помилки накопичуються. Утиліта Slepenh дозволяє легко уникнути цього накопичення помилок.
sleepnh
це краще, ніж sleep
ви (ви говорите лише, що інші відповіді використовують sleep 1
- чого вони не роблять) , тільки ОП використовує це) та ii) де його отримати та як встановити, оскільки це не стандартний інструмент.
sleep
та sleepenh
в ньому. У всякому разі, я, мабуть, не був досить зрозумілий у цьому, тому в кінці кінців розширив більше. Проблеми з точністю до мілісекунд - це те, що ви отримуєте, коли дзвоните sleep
один раз. Вони накопичуються з часом, і в якийсь момент це помітно. Я не сказав, що інші використовують лише sleep 1
. Я сказав, що вони використовують sleep 1
або зайняту петлю. Що вони ще роблять. Покажіть мені зустрічний приклад. Відповіді, які 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
Приклад пітона:
#!/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 хвилин помдоро - 240х80 = розмір терміналу з 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мс.