A stopwatch command for manually timing things: Download (3.5K)
This command line timer should run on any unix and has been tested on linux and Mac OS X.
Here is an example run, and following is a discussion of the script's internals for those interested...
Space for lap | ? for split | Ctrl-C to stop | Space to start...
1.28 (1)
3.15 (2)
2.39 (3)
6.87
This shell script has an unusual requirement in that it must respond immediately to a user at a terminal, entering 3 separate inputs (stop, lap, split). As I see it, there are 2 options to do that, "raw" mode and signals.

Raw Mode

Setting the terminal into raw mode, where characters are immediately progagated up to the application is problematic because if you hit the arrow keys for example, multiple characters will be present in the input buffer, which will cause the loop to execute multiple times. Dear lazy web, is there any way to clear the input buffer in a shell script?
while true; do
    echo -n "Hit a key: "
    stty raw
    char=`dd if=/dev/tty bs=1 count=1 2>/dev/null`
    stty -raw
    echo -e "\ngot [$char]"
done

Signals

I went with this option because it maps explicit keys to operations, rather than responding to any key as in raw mode. Also it doesn't change the terminal away from its default "cooked" mode. We need 3 separate user inputs as mentioned above and neatly there are 3 interrupts that can be generated by a user at a terminal: SIGTSTP (^Z), SIGINT (^C) and SIGQUIT (^\). Now we also want the signals to terminate a process, since timing the run length of a process is the method I used to obtain lap times. I couldn't get SIGTSTP to do this, so I used ^C, ^\ and ^D with the `cat` program.

Note there is an issue where "eof" (^D), since it doesn't actually generate a signal, it is ignored unless it's on a new empty line (or is entered twice). Also since "eof" (^D) doesn't generate an signal, there may be an extra delay in processing on heavily loaded systems where this script and its subprocesses take a while to be scheduled. In general on heavily loaded systems, one can get better response by running the script using the sudo nice -n-20 sw command. Talking about delays, SIGQUIT (^\) can also have delayed processing on ubuntu due to this bug.

Now ^\ and ^D etc. are awkward to type, so one can map the actual characters used to generate these on a terminal using the `stty` command. This is illustrated in the example script using the signalling method below:

ulimit -c 0 #no cores from SIGQUIT
trap '' SIGTSTP #ignore Ctrl-Z
save_tty=`stty -g` && trap "stty $save_tty" EXIT #restore tty on exit
stty quit ' ' #space for laps rather than Ctrl-\
stty eof  '?' #? for splits rather than Ctrl-D
stty -echo #don't echo input

echo "space for lap | ? for split | Ctrl-C to stop"
while true; do
    cat >/dev/null
    echo "got [$?]"
done

Portability

I've tested this script specifically on fedora (/bin/sh -> bash), ubuntu (/bin/sh -> dash), and Mac OS X (where date doesn't support nanoseconds). `bash` when started through /bin/sh supposedly runs in POSIX mode, but there are many instances where it deviates from this. So I advise to develop using `dash` and bash should support the script by default. As for date not outputting nanoseconds on Mac OS X, I was able to work around this by using python which is installed by default.
© Aug 2 2007