29

I would like to have a count down of 5 minutes, updating every second and showing the result on the same line. Is this even possible with Bash scripting?

3
  • What does the countdown do? You need to be a little more specific about the whole thing. Aug 21, 2013 at 9:41
  • This is absolutely possible. If you tell us why (what actual system/network administration problem you're trying to solve) we can tell you which of the many available methods to do it will likely work best for you. If it's a general "How do I do this in a bash script?` question your question is probably better suited to Unix & Linux -- let me know and I can migrate it there for you :)
    – voretaq7
    Aug 21, 2013 at 14:04

2 Answers 2

61

This works from Bash shell:

secs=$((5 * 60))
while [ $secs -gt 0 ]; do
   echo -ne "$secs\033[0K\r"
   sleep 1
   : $((secs--))
done

The special character \033[0K represents an end of line which cleans the rest of line if there are any characters left from previous output and \r is a carriage return which moves the cursor to the beginning of the line. There is a nice thread about this feature at stackoverflow.com.

You can add own commands or whatever in the while loop. If you need something more specific please provide me more details.

4
  • Do you mean \033[K as per ascii-table.com/ansi-escape-sequences.php instead of 0K? Oct 4, 2015 at 0:04
  • I put \r at the beginning to put cursor at the end of line (which prevent it to hide the first character). Here is the updated version: gist.github.com/boillodmanuel/676b3af823fae4177f1d0b41a6f23442 Thanks Nov 8, 2019 at 10:11
  • 1
    Note for anyone confused by the leading colon on line 5: That is the null operator, allowing the following $((...)) construction to be evaluated without being interpreted as a command. However, I believe the same effect can be had more simply by just putting ((secs--)) in place of : $((secs--)).
    – shawkinaw
    Jan 13, 2020 at 15:33
  • arithmetic expression: expecting primary: "secs--"
    – Aadam
    Jan 2, 2022 at 21:40
15

Here's one with an improvement of right output format (HH:MM:SS) with proper leading zeros and supporting hours:

#!/bin/bash

m=${1}-1 # add minus 1 

Floor () {
  DIVIDEND=${1}
  DIVISOR=${2}
  RESULT=$(( ( ${DIVIDEND} - ( ${DIVIDEND} % ${DIVISOR}) )/${DIVISOR} ))
  echo ${RESULT}
}

Timecount(){
        s=${1}
        HOUR=$( Floor ${s} 60/60 )
        s=$((${s}-(60*60*${HOUR})))
        MIN=$( Floor ${s} 60 )
        SEC=$((${s}-60*${MIN}))
     while [ $HOUR -ge 0 ]; do
        while [ $MIN -ge 0 ]; do
                while [ $SEC -ge 0 ]; do
                        printf "%02d:%02d:%02d\033[0K\r" $HOUR $MIN $SEC
                        SEC=$((SEC-1))
                        sleep 1
                done
                SEC=59
                MIN=$((MIN-1))
        done
        MIN=59
        HOUR=$((HOUR-1))
     done
}

Timecount $m

Gives an output that looks like this:

02:04:15
1
  • The output isn't quite HH:MM:SS. For single digit minutes or seconds, you could see 00:4:5.
    – chishaku
    Oct 14, 2015 at 14:58

Not the answer you're looking for? Browse other questions tagged .