題 有沒有辦法在終端顯示倒計時或秒錶計時器?


如何在Linux終端上顯示實時倒數計時器?是否有一個現有的應用程序,或者甚至更好的一個內襯來做到這一點?


127
2018-06-24 20:13


起源


關於SU持有:我認為這屬於“計算機軟件”而沒有“要求購物或產品推薦”。我不是要求建議;我問是否存在某些事情。當我最初問這個問題時,我期待的可能是“是的,這是內置的-nix腳本”。如果我能重組這個問題,我會的。 - tir38
這就是我試圖做的事情。就我而言,在編輯之後它就是主題,我已經投票重新打開了它。 - terdon
@terdon謝謝,我看到這是一個更好的問題。 - tir38


答案:


我不確定你為什麼需要 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(或您喜歡的任何shell)函數將它們組合成簡單的命令。在bash中,將這些行添加到您的 ~/.bashrc (該 sleep 0.1 將使系統在每次運行之間等待1/10秒,這樣您就不會對CPU進行垃圾郵件):

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小時。它應該工作,但如果沒有,請告訴我。


166
2018-06-24 22:11



我把這些不錯的功能添加到我的 .zshrc 我讀完你的答案之後。今天我用過 countdown 第一次,並註意到相當高的CPU使用率。我加了一個 sleep 0.1 (我不知道所有系統是否支持小數秒的睡眠時間),這大大改善了。缺點當然是顯示精度不太準確,但我可以忍受最大偏差。 100毫秒。 - mpy
@mpy謝謝你提到這一點。這樣做時,我的CPU使用率約為3% bash,我可以忍受(雖然它 是 高於我的預期,我也將睡眠添加到我自己的.bashrc中。 - terdon
@terdon:我必須承認我在一台相當老的機器上使用它(2007?!),CPU上升到18%......否則我可能不會注意到。 - mpy
剛剛找到了這個答案。我發現在秒錶功能的echo語句開頭放回車符是很方便的,因為它意味著殺秒錶並沒有覆蓋當前的秒錶時間:echo -ne“\ r $(date -u --date @ $ ((date +%s  - $ date1))+%H:%M:%S)“; - mkingston
@chishaku:在OS X上,這似乎對我有用: echo -ne "$(date -ju -f %s $(($date1 - 日期+%s)) +%H:%M:%S)\r"; - user1071847


我最喜歡的方式是:

開始:

time cat

停止:

ctrl+c

正如@wjandrea在下面評論的那樣,另一個版本將運行:

time read

並按 Enter 停止


85
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


29
2018-06-06 07:06



@DoktoroReichard:嗯,這是一個下載鏈接。 - harrymc
不適用於python 3.x. - Suhaib
@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#

編輯:我打開了一堆鏈接,我認為這是特定於osx的,對不起。離開我的答案,以便其他人知道BSD的離開。


12
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


我把非常好的terdon的答案結合起來,同時顯示自開始以來的時間,以及時間到結束的時間。還有三種變體,所以它更容易調用(你不必做bash數學),它也是抽象的。 使用示例

{ ~ }  » 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終端(通過Linux命令行播放mp3或wav文件)或cygwin(cat /path/foo.wav > /dev/dsp  在babun / win7)為我工作,你有一個 簡單靈活的計時器帶鬧鐘


4
2018-02-01 14:42





另一種方法

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





我最終編寫了自己的shell腳本: github要點

#!/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 腳本中的工具。相反,建議的解決方案要么使用a 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秒。

編輯

Slepenh工具來自Debian中的同名包及其衍生產品,如Ubuntu。對於沒有它的發行版,它來自 https://github.com/nsc-deb/sleepenh

Slepenh的優點在於,它能夠考慮到在循環期間處理除睡眠之外的其他事物而累積的小延遲。即使有人願意 sleep 1 在一個循環中10次,由於執行的開銷很小,整體執行將花費10秒多一點 sleep 並迭代循環。這個錯誤慢慢累積,並會隨著時間的推移使我們的秒錶計時器越來越不精確。要解決這個問題,必須每次循環迭代計算精確的睡眠時間,通常略小於一秒(對於一秒間隔的計時器)。 Slepenh工具為您完成此任務。


3
2017-11-24 15:38



我不明白這給我的答案帶來了什麼好處 sleep 0.1。什麼是 sleepnh (我在Arch repos中找不到它)它與它有什麼不同 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