Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

How can I display a real-time countdown timer on the Linux terminal? Is there an existing app or, even better, a one liner to do this?

share|improve this question
    
regarding SU hold: I think this falls under "computer software" without "asking for a shopping or product recommendation". I'm not asking for recommendations; I'm asking if something even exists. When I initially asked the question, I was anticipating maybe a "yeah there is this built-in -nix script". If I can restructure the question, I will. –  tir38 Jun 26 '13 at 17:40
    
That's what I tried to do. It is on topic after my edit as far as I am concerned and I have voted to reopen it. –  terdon Jun 26 '13 at 17:41
    
@terdon thanks, I see how that is a better question. –  tir38 Jun 28 '13 at 2:19

9 Answers 9

up vote 40 down vote accepted

I'm not sure why you need beep, if all you want is a stopwatch, you can do this:

while true; do echo -ne "`date`\r"; done

That will show you the seconds passing in realtime and you can stop it with Ctrl+C. If you need greater precision, you can use this to give you nanoseconds:

while true; do echo -ne "`date +%H:%M:%S:%N`\r"; done

Finally, if you really, really want "stopwatch format", where everything starts at 0 and starts growing, you could do something like this:

date1=`date +%s`; while true; do 
   echo -ne "$(date -u --date @$((`date +%s` - $date1)) +%H:%M:%S)\r";
done

For a countdown timer (which is not what your original question asked for) you could do this (change seconds accordingly):

seconds=20; date1=$((`date +%s` + $seconds)); 
while [ "$date1" -ne `date +%s` ]; do 
  echo -ne "$(date -u --date @$(($date1 - `date +%s` )) +%H:%M:%S)\r"; 
done

You can combine these into simple commands by using bash (or whichever shell you prefer) functions. In bash, add these lines to your ~/.bashrc (the sleep 0.1 will make the system wait for 1/10th of a second between each run so you don't spam your CPU):

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

You can then start a countdown timer of one minute by running:

countdown 60

You can countdown two hours with:

countdown $((2*60*60))

or a whole day using:

countdown $((24*60*60))

And start the stopwatch by running:

stopwatch
share|improve this answer
    
Given the thorough, well explained answer, I gotta give you the check mark! –  tir38 Jun 28 '13 at 2:19
3  
I added these nice functions to my .zshrc right after I read your answer. Today I used countdown the first time and noticed a rather high CPU usage. I added a sleep 0.1 (I don't know if a sleep time of a fractional second is supported on all systems) which improved that a lot. The drawback is of course a less accurate display accuracy, but I can live with a deviation of max. 100ms. –  mpy Jul 5 '13 at 14:45
    
@mpy thanks for mentioning that. I am getting ~3% CPU usage when doing this in bash, I can live with that (though it is higher than I expected and I have also added the sleep to my own .bashrc). –  terdon Jul 5 '13 at 14:59
1  
Just found this answer. I found putting the carriage return at the beginning of the echo statement in the stopwatch function was handy as it meant killing the stopwatch didn't overwrite the current stopwatch time: echo -ne "\r$(date -u --date @$((date +%s - $date1)) +%H:%M:%S)"; –  mkingston Jun 16 at 12:51
1  
@orip fair enough, done. –  terdon Nov 19 at 12:47

I've used this one:

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
)

Example:

 countdown "00:07:55"

Here's a source.

share|improve this answer

I ended up writing my my own shell script: github gist

# script to create timer in terminal
# Jason Atwood
# 2013/6/22
#!/bin/sh

# 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 
share|improve this answer
1  
Nice script, +1. Just so you know, that is a countdown timer, not a stopwatch. –  terdon Jun 25 '13 at 12:17
    
ha you're right, thats what I really wanted. I'll update my naming. –  tir38 Jun 26 '13 at 17:31

I was looking for the same thing and ended up writing something more elaborate in Python:

This will give you a simple 10-second countdown:

sudo pip install termdown
termdown 10

Source: https://github.com/trehn/termdown

share|improve this answer
    
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. –  Doktoro Reichard Jun 6 at 8:21
    
@DoktoroReichard: Well, this is a download link. –  harrymc Jun 6 at 10:42
    
doesn't work with python 3.x –  Suhaib Jun 20 at 2:18
    
@Suhaib: It should and does for me. Please raise an issue on GitHub with more info. –  trehn Jun 27 at 9:23

This is for a stopwatch with hundredths of second

#!/usr/bin/awk -f
func z() {
  getline < y
  close(y)
  return $0
}
BEGIN {
  y = "/proc/uptime"
  x = z()
  while (1)
    printf "%s\r", z() - x
}

Example

share|improve this answer
#!/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()
share|improve this answer

Another approach

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

If one wants a signal when it hits zero, one could e.g. build it with a command that returned a non-zero exit status at zero and combine it with watch -b, or something, but if one wants to build a more elaborate script, this is probably not the way to go; it is more of a "quick and dirty one-liner" type solution.


I like the watch program in general. I first saw it after I had already written countless while sleep 5; do loops to different effects. watch was demonstrably nicer.

share|improve this answer

For future reference, there is a command line tool called µTimer with very straightforward command line options for a countdown/count-up timer.

share|improve this answer

If you would like a compile-able program for whatever reason, the following would work:

#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;
}

This can be used in other programs as well and easily ported, if a bash environment isn't available or you just prefer using a compiled program

github

share|improve this answer
    
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. –  Ƭᴇcʜιᴇ007 Aug 18 at 18:06
    
Thanks for the input! –  elder4222 Aug 18 at 22:19

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.