Sometimes, while writing some code, I can not keep track of time and end up not really knowing the time I have spent on it.

So to keep an eye on this I can make sure to look at my watch and writing down the starting time but this is something I would not be able to do all the time. It would also not create a log of what I have done in the past.

To keep track of time I made a sort of "stopwatch" in a bash script. As soon as I start it with the name of the "thing" I am doing it will keep showing me the time I have spent and as soon as I stop it will write that to a log file.

So I started creating a new bash script with my localScript bash script creator.

localScript timer

#!/usr/bin/env bash

if [[ -z "$1" ]]; then
        echo "You need to set a project name as the first variable"
        exit 0
fi

PROJECT=$1

FILENAME='time.log'

START_TIME=$SECONDS

There I set the name of the log file I will write into, make sure a project name is defined and start the timer.

The script would need to keep running until I stopped it and, just before ending, it would need to write to a file. In order to get this working I added a while true loop :

while true
do
        DURATION=$(( SECONDS - $START_TIME ))
        echo "$DURATION"
        sleep 10
done

Then I added a trap command to get the script to write to a log file when stopped :

function writeLog()
{
        echo "$PROJECT date: $(date +'%d-%m-%Y') / user: $USER / time:  $DURATION" >> $FILENAME
}

trap writeLog EXIT

Now when running the timer "test project" script you will see this in the Command Line :

timer "test project"
test project time 0
test project time 10
test project time 20

As soon as you exit the script with CTRL+C it will write to the time.log file :

test project date: 18-03-2021 / user: dennis / time: 12421

It sets the date, the username and the time spent on the project.

This was all good, but I wanted to make the log a little more readable and write the time from just seconds into a formatted string, so I added a function :

function secondsToTimeString() 
{
        echo "$(($1/3600))h:$(($1%3600/60))m:$(($1%60))s"
}

I also did not want it to write on many lines, so I added the -ne option to my echo :

echo -ne "$PROJECT time $(secondsToTimeString $DURATION)                \r"

This now works pretty well and can be attached to other commands to keep track of time. Here is the full script :

#!/usr/bin/env bash

if [[ -z "$1" ]]; then
        echo "You need to set a project name as the first variable"
        exit 0
fi

PROJECT=$1

FILENAME='time.log'

START_TIME=$SECONDS

function secondsToTimeString() 
{
        echo "$(($1/3600))h:$(($1%3600/60))m:$(($1%60))s"
}

function writeLog()
{
        echo "$PROJECT date: $(date +'%d-%m-%Y') / user: $USER / time:  $(secondsToTimeString $DURATION) [$DURATION]" >> $FILENAME
}

trap writeLog EXIT

while true
do
        DURATION=$(( SECONDS - $START_TIME ))
        echo -ne "$PROJECT time $(secondsToTimeString $DURATION)                \r"
        sleep 10
done

When you run it, it will show you :

 ➜  ~ timer "Writing a blog post about making a timer"
Writing a blog post about making a timer time 0h:12m:30s   

And the log file :

➜  ~ cat time.log
Writing a blog post about making a timer date: 18-03-2021 / user: dennis / time:  0h:1m:50s [750]

In my case it will create a time.log file wherever you run the script. This is handy for me as I will generate one in the root of the project I am working on. If you want a more general log file you can change the FILENAME variable to something like /home/username/time.log so that wherever you run the script from data will be added to the same log file in your home directory.