scripts

Setting a Timer

Sometimes I need a timer to focus on something and to alert me when to stop. Remember, we are real commandliners, so we do not want those fancy applications with a lot of features, we need a script ;-) so here it is:

#!/bin/bash

usage() {
  name=`basename $0`
  echo "Usage: $name hh:mm:ss"
  echo "Example: $name \"00:15:30\""
}
 
if [ $# != 1 ]
then  
  usage 
  exit  
fi
  
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

It works in any POSIX shell.

I was writing one but I found this thread of the UNIX and linux forum where the user cfajohnson solves it in a better way.

The code:

sleep 1 &
...
wait

minimizes the skew of the loop, so every cycle is as close to 1 second as possible.

I have not included the final beep in the script. You can do it with the usual:

printf ("\a")

which works on all unix-like systems.

In linux you can use the beep command that allows you to control pitch, duration, and repetitions, for example:

$ beep -f 300.7 -r 2 -d 100 -l 400

makes 2 repetitions of a beep at 300.7 Hz for 400 milliseconds and a delay between repetitions of 100 milliseconds.

In OS X you can play with the say command:

$ say "You deserve some rest"

3 Comments

  • On 10.01.10 John Baber said:

    What about ‘at’ ?

    $ at 2:03pm
    warning: commands will be executed using /bin/sh
    at> beep
    at> CTRL-D
    job 1 at Fri Oct 1 14:03:00 2010

  • On 10.02.10 rafacas said:

    I didn’t think of the ‘at’ command. That is the simplest way of doing it… Very clever :)
    I’m using the timer script for other scripts and I like seeing the countdown.

  • On 11.01.10 prauscher said:

    Hey,

    at requires the use of absolute dates, so this timer-script is useful then ;)
    i added some code to ease up usage, so timer 3:23 will also work. Likewise timer 10 will show a timer down from 10:

    #!/bin/bash

    usage() {
    name=`basename $0`
    echo "Usage: $name [[hh:]mm:]ss"
    echo "Example: $name \"00:15:30\""
    }

    if [ $# -ne 1 ]
    then
    usage
    exit
    fi

    IFS=:
    set -- $*
    secs=0

    if [ $# -gt 3 ]
    then
    usage
    exit
    fi

    if [ $# -eq 3 ]
    then
    secs=$(($secs + ${1#0} * 3600))
    shift
    fi

    if [ $# -eq 2 ]
    then
    secs=$(($secs + ${1#0} * 60))
    shift
    fi

    if [ $# -eq 1 ]
    then
    secs=$(($secs + ${1#0}))
    shift
    fi

    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

speak up

Add your comment below, or trackback from your own site.

Subscribe to these comments.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*Required Fields