如何在Linux终端上显示实时倒数计时器?是否有一个现有的应用程序,或者甚至更好的一个班轮来执行此操作?

#1 楼

我不确定为什么需要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中,将这些行添加到您的~/.bashrcsleep 0.1将使系统在每次运行之间等待1/10秒,这样您就不会对CPU造成垃圾邮件):

function countdown(){
   date1=$((`date +%s` + )); 
   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` + ));
    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
}


请注意,由于我真的不想等待24小时,因此stopwatch函数没有经过几天的测试。它应该可以,但是如果不能,请通知我。

评论


在阅读您的答案后,我将这些漂亮的功能添加到了.zshrc中。今天,我第一次使用倒数计时,注意到CPU使用率很高。我增加了一个睡眠0.1(我不知道所有系统是否都支持小数秒的睡眠时间),这改善了很多。缺点当然是显示精度较差,但我可以承受最大偏差。 100毫秒

–mpy
13年7月5日在14:45

@mpy感谢您提及。在bash中执行此操作时,我获得了约3%的CPU使用率,我可以忍受(尽管它比我预期的要高,而且我还将睡眠添加到了自己的.bashrc中)。

– terdon
13年5月5日在14:59

刚找到这个答案。我发现将回车符放在秒表函数的echo语句的开头很方便,因为这意味着杀死秒表不会覆盖当前的秒表时间:echo -ne“ \ r $(date -u --date @ $ ((date +%s-$ date1))+%H:%M:%S)“;

–麦金斯顿
14年6月16日在12:51

@chishaku:在OS X上,这似乎对我有用:echo -ne“ $(date -ju -f%s $(($ date1-date +%s))+%H:%M:%S)\ r“;

–user1071847
16年7月11日在16:26

使用sox包时,我会在倒计时结束时添加一个不错的声音:play -q -n synth 2 pluck C5。

– Pablo A
18年5月15日在23:59

#2 楼

我最喜欢的方式是:

开始:

time cat


停止:

ctrl+c



如下面的@wjandrea所述,将运行另一个版本:

time read


,然后按Enter停止

评论


+1。 Lifehacker具有此技巧。

–内森·亚瑟(Nathan Arthur)
2015年9月9日在22:18

类似,但是您可以按Enter停止:已读时间

– wjandrea
16年5月25日在1:07



在zsh中,time读取失败,但是时间(read)有效。

– Sparhawk
16-10-7在4:53

但问题是,您必须取消或完成时间才能看到时间。当您重新启动它时,计时器重新开始。

–塞尔菲·卡尔斯塔尔(Zelphir Kaltstahl)
17-10-18在8:50

如此漂亮的解决方案。容易记住。

– jlh
20 Dec 26 '14:12

#3 楼

我一直在寻找相同的东西,最终用Python编写了更详细的东西:

这将为您提供10秒的简单倒计时:

sudo pip install termdown
termdown 10


来源:https://github.com/trehn/termdown

评论


不适用于python 3.x

– Suhaib
2014年6月20日在2:18

@Suhaib:应该而且应该为我做。请在GitHub上提出问题,以获取更多信息。

– Trehn
14年6月27日在9:23

看起来很棒!谢谢!

– phrogg
20年5月31日在17:43

#4 楼

使用leave(至少对BSD后代有效):

man leave


设置计时器15分钟:

leave +0015
Alarm set for Thu Nov  3 14:19:31 CDT 2016. (pid 94317)


评论


离开也可以在Linux中使用,但是首先您必须从默认存储库安装离开程序。

–卡雷尔
16-11-4在4:10



在Mac上离开工作并产生蜂鸣声

–德米特里
20年1月9日,18:14

很好,除了当前它不做秒,所以不可能倒计时30秒,例如

–nonopolarity
20 Dec 4'在10:56

#5 楼

我曾经用过这个:

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"


这里是源码。

评论


兼容POSIX-在OS X上可用:)

– djule5
15年2月24日在1:02

Arch Linux上的错误:倒计时:4:数学表达式错误:操作数应为“ * 60 +”

–Chalist
19/12/18在1:03



@Chalist可能是您正在使用Zsh。在Bash上运作良好

–nonopolarity
20 Dec 12'在20:47

#6 楼

简短答案:
for i in `seq 60 -1 1` ; do echo -ne "\r$i " ; sleep 1 ; done

解释:
我知道有很多答案,但是我只想发布一些与OP问题非常接近的东西,我个人认为我的确是“单人倒计时”在终端”。我的目标是:

一个班轮。
倒计时。
易于记忆和键入控制台(无功能和繁琐的逻辑,仅适用于bash)。
不需要要安装的其他软件(即使我在那里没有root用户,也可以在通过ssh访问的任何服务器上使用)。

工作方式:


seq打印从60到1的数字。

echo -ne "\r$i "将插入号返回到字符串的开头,并打印当前的$i值。如果前一个值比当前$i(10-> 9)字符长,则需要覆盖后一个空格。


评论


这对于我在Mac OS上用于bash脚本的用例来说效果最好。有关其工作原理的说明特别有用。

–詹姆斯·坎贝尔
19年8月12日在17:56

#7 楼

这是秒表的百分之一秒:

 #!/usr/bin/awk -f
function z() {
  getline < "/proc/uptime"
  close("/proc/uptime")
  return q4312079q
}
BEGIN {
  x = z()
  while (1) {
    y = z()
    printf "%02d:%05.2f\r", (y - x) / 60, (y - x) % 60
  }
}
 


示例

评论


不错的纯Linux解决方案!我喜欢没有外部电话。注意,我的Debian系统在/ proc / uptime中有两个值,第二个大概是指我以前的正常运行时间。可以通过更改第5行以返回$ 1来对此脚本进行调整以解决该问题。

–亚当·卡兹(Adam Katz)
17年11月16日23:00



#8 楼

另一种方法
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表现得更好。

#9 楼

我很惊讶没有人在他们的脚本中使用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 $@"
"sleep" &
counterpid=$!
trap "exit" INT TERM
trap "kill 0" EXIT
sleep "$@"
kill $counterpid
 


该脚本既可以用作秒表(递增计数直到被中断),也可以用作运行指定时间的计时器。由于使用了sleep命令,因此该脚本允许以与sleep 1所允许的精度相同的精度指定持续时间。在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 10次,由于执行q4312079q和迭代循环会产生较小的开销,因此整个执行将花费10秒以上的时间。该错误会慢慢累积,随着时间的流逝,会使我们的秒表计时器越来越不精确。为了解决这个问题,每个循环迭代必须计算出精确的睡眠时间,通常略小于一秒(间隔时间为一秒)。 sleepenh工具为您完成此操作。

评论


我不明白这给我的答案带来了什么好处,我的答案也使用睡眠0.1。什么是sleepnh(我在Arch仓库中找不到它),它与睡眠有何不同?据我所知,您基本上在做与我上面的回答相同的事情。我想念什么?

– terdon
17年1月26日在12:28

@terdon Sleepenh来自这里github.com/nsc-deb/sleepenh仅仅说睡眠5的问题是,您没有完全睡5秒钟。尝试例如time sleep 5,您会看到运行命令花费的时间略超过5秒。随着时间的流逝,错误会累积。 sleepenh实用程序可轻松避免这种错误累积。

– josch
17年1月27日在8:04



好。在我的系统上,我看到0.002秒的错误。我真的怀疑有人会使用这种工具并期望比毫秒精度更好,但是如果您至少编辑答案会更好,并且i)解释为什么sleepnh比睡眠更好(您只说其他答案使用sleep 1 -他们没有,只有OP会使用它,并且ii)因为它不是标准工具,所以在哪里获得它以及如何安装它。

– terdon
17年1月27日在13:12

@terdon我在第一段中解释了sleep和sleepenh之间的区别。无论如何,我可能对此还不够清楚,所以最后我进一步扩展了这一点。毫秒精度问题是您致电一次睡眠时会遇到的问题。他们随着时间的推移而积累,在某些时候值得注意。我并不是说其他​​人只使用睡眠1。我是说他们使用睡眠1或busyloop。他们仍然这样做。给我看一个反例。睡眠为0.1的答案与睡眠为1的答案相同,只不过它们会更快地累积错误。

– josch
17年1月28日在6:49

我从答案中寻找至少有人承认您解决了问题的人。

– Mariotomo
18年2月20日在14:11

#10 楼

我将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` + ));
   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  seconds"
  time_func 
}

function time_minutes()
{
  echo "Counting to  minutes"
  time_func *60
}

function time_hours()
{
  echo "Counting to  hours"
  time_func *60*60
}

function time_flexible()  # Accepts flexible input hh:mm:ss
{
    echo "Counting to "
    secs=$(time2seconds )
    time_func $secs
}

function play_sound()  # Adjust to your system
{
    cat  > /dev/dsp
}

function time2seconds() # Changes hh:mm:ss to seconds. Found in some other Stack Exchange answer
{ 
    a=( ${1//:/ }) 
    echo $((${a[0]}*3600+${a[1]}*60+${a[2]})) 
}


通过在Linux终端中播放声音(通过Linux命令行播放MP3或WAV文件)或Cygwin(cat /path/foo.wav > /dev/dsp在Babun / Windows 7中对我有用)来组合声音,并且您有一个带有闹钟的简单定时器!

评论


Babun项目已中止。

– Peter Mortensen
20 Mar 7 '20 at 17:44

#11 楼

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


评论


拱门错误:请尝试使用“ date --help”以获取更多信息。 ate:无效的选项-'v'

–Chalist
19/12/18在1:12

为什么要安装URL包含“阴险”的内容? -“ 2。邪恶或看似邪恶的;表明潜伏的危险或伤害。”

– Peter Mortensen
20 Mar 7 '20 at 18:06



我同意,“罪魁祸首”对于软件安装人员来说是一个可怕的名称选择。

– Cory Klein
20 Mar 7 '20 at 20:56

#12 楼

我最终编写了自己的shell脚本: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 visibility

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


评论


不错的脚本,+ 1。请注意,这是一个倒数计时器,而不是秒表。

– terdon
2013年6月25日12:17

哈,你说得对,那就是我真正想要的。我将更新我的命名。

–tir38
2013年6月26日17:31

#13 楼

看一下TermTime。这是一个不错的基于终端的时钟和秒表:

pip install termtime


#14 楼

供以后参考,有一个名为µTimer的命令行工具,其中包含用于倒数/递增计时器的非常简单的命令行选项。

#15 楼

只需在UTC时间中使用watch + date。您还可以安装一些大显示屏包装...

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 /在屏幕上创建大彩色文本横幅/

#16 楼

一个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()




#17 楼

假设您是OS X上正在寻找命令行秒表的人。假设您不想安装gnu工具,而只想与Unix date一起运行。

在这种情况下,请按照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
}


评论


我在OS X El Capitan上尝试过,出于某种原因,它以16:00:00开头

–nonopolarity
2015年10月29日,下午2:34

好的,我找到了答案。将使用date -ujf代替date -jf,它将以00:00:00开头

–nonopolarity
20 Dec 4'在18:20

#18 楼

只是一个内衬

N=100; while [[ $((--N)) >  0 ]]; do  echo  $N |  figlet -c && sleep 1 ; done


screenhost



我们也可以使用ANSI清除屏幕(终端)使用2J格式的转义序列。

N=100; while [[ $((--N)) >  0 ]]; do  echo -e "3[2J3[0m"; echo "$N" |  figlet -c && sleep 1 ; done



注意

如果需要BIG字体,则需要安装figlet命令,否则请删除figlet零件。

N=100; while [[ $((--N)) >  0 ]]; do  echo  $N  && sleep 1 ; done


,您可以使用lolcat ...获得漂亮的输出...

N=100; while [[ $((--N)) >  0 ]]; do  echo "$N" |  figlet -c | lolcat &&  sleep 1 ; done


screenhsot



#19 楼

今天早些时候,在寻找一个用于显示车间大型倒数计时器的术语应用程序时,发现了这个问题。这些建议都不是我真正需要的,因此我在Go中很快将另一个建议放到了一起:https://github.com/bnaucler/cdown

由于问题已经得到足够的回答,请考虑一下为了后代。

#20 楼

$ sleep 1500 && xterm -fg yellow -g 240x80&

当那个带有黄色文本的大终端跳起来时,该起床拉伸了!

注意: >-1500秒= 25分钟pomodoro
-240x80 =终端大小,包含240个字符行和80行。

为我显示一个屏幕。

信用:http://www.linuxquestions.org/questions/linux-newbie-8/countdown-timer-for-linux-949463/

评论


但是直到达到零,它才显示任何内容。问题包含“显示实时倒数计时器”。

– Peter Mortensen
20 Mar 7 '20 at 18:04

#21 楼

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


#22 楼

这类似于已接受的答案,但是terdon的countdown()给了我语法错误。不过,这对我来说非常有用:

function timer() { case "" in -s) shift;; *) set $(( * 60));; esac; local S=" "; for i in $(seq "" -1 1); do echo -ne "$S\r $i\r"; sleep 1; done; echo -e "$S\rTime's up!"; }


您可以将其放在.bashrc中,然后执行:timer t(其中t是时间,以分钟为单位)。 >

#23 楼

如果您的系统已经有Ruby,则可以使用:
#!/usr/bin/env ruby

n = ARGV[0].to_f
go_beginning_of_line = "3[G"
clear_till_end_of_line = "3[K"

time_end = Time.now + n
while Time.now < time_end
    more = time_end - Time.now
    print "#{go_beginning_of_line}Counting down #{more.round(1)} of #{n} seconds#{clear_till_end_of_line}"
    sleep [0.1, more].min
end
puts "#{go_beginning_of_line}Counting down #{n} seconds. \a\aDone.#{clear_till_end_of_line}"


#24 楼

如果您出于某种原因想要一个可编译的程序,则可以使用以下程序:

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


如果在Bash环境中,它也可以在其他程序中使用,并且可以轻松移植。不可用,或者您只喜欢使用已编译的程序。

GitHub