Unix / Linux: Display Running Clock in Terminal

Objective: On a Unix or Linux, display a running clock on the top right hand corner of a shell terminal.

This can be done either by ANSI escape sequences or tput. Using tput is my preferred method as ANSI escape sequences tend to mess around with my cursor position – even though I use the save and restore cursor position escape sequences. Nevertheless, let’s look at both examples.

Before we start, let’s look at our clock output.

$ date
Sun Jan 10 15:46:13 SGT 2016

It is by default 28 characters long. So to print the date on the top right corner, we will need to know the column size and subtract 27 from it. We can get the column size from the $COLUMNS shell variable. On my shell terminal, my column length is 160 characters.

$ echo $COLUMNS
160

After printing the clock, we will need to restore the cursor position to the original place. This is where “ESC[s” and “ESC[u” will come in handy. They are used to save cursor position and restore cursor position respectively. But somehow, this is not really working for me very well. Cursor positions are not really getting restored to the original position. But anyway, let’s look at the shell code. Cursor positions are 1-based and not 0-based here.

$ while sleep 1; do printf "\e[s\e[1;%sH%s\e[u" $((COLUMNS-27)) "$(date)"; done &

On your shell terminal, run the above code, and you should get a clock on the top right corner that updates itself every second.

With tput, the concept is going to be the same. We save the cursor position, goto the top right corner, print the date and restore the cursor position. Let’s look at an example. Note that cursor positions are 0-based with tput.

$ while sleep 1; do tput sc; tput cup 0 $(($COLUMNS-28)) ; date; tput rc; done &

With tput, cursors are restored to the correct position – at least on the computers that I have tested.

ibrahim = { interested_in(unix, linux, android, open_source, reverse_engineering); coding(c, shell, php, python, java, javascript, nodejs, react, vuejs); plays_on(xbox, ps4); linux_desktop_user(true); }