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"
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
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.
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