Post your handy utility scripts!

Here is a digital clock I just made as an exercise in bash scripting:

#!/usr/bin/env bash
# A rather nice looking digital clock in the terminal. 

function cleanup_() {
  printf '\033[?25h' # unhide cursor
  stty echo 2>/dev/null
}
trap cleanup_ EXIT

REFRESH_INTERVAL=0.2  # display the clock every 0.2 seconds, adjust if necessary
TIME_FORMAT="%H:%M:%S" # change to "%I:%M:%S" for 12-hour format

# Feel free to modify the FONT, the only restriction is that all characters are
# of equal height. There should be 11 characters, in this order: "0123456780:"
FONT=(
"█▀▀█ "
"█  █ "
"█  █ "
"▀▀▀▀ "
"   █ "
"   █ "
"   █ "
"   ▀ "
"▀▀▀█ "
"▄▄▄█ "
"█    "
"▀▀▀▀ "
"▀▀▀█ "
"▄▄▄█ "
"   █ "
"▀▀▀▀ "
"█  █ "
"█▄▄█ "
"   █ "
"   ▀ "
"█▀▀▀ "
"█▄▄▄ "
"   █ "
"▀▀▀▀ "
"█▀▀▀ "
"█▄▄▄ "
"█  █ "
"▀▀▀▀ "
"▀▀▀█ "
"   █ "
"   █ "
"   ▀ "
"█▀▀█ "
"█▄▄█ "
"█  █ "
"▀▀▀▀ "
"█▀▀█ "
"█▄▄█ "
"   █ "
"▀▀▀▀ "
"    "
" ▀  "
"    "
" ▀  "
)
FONT_HEIGHT=$(( ${#FONT[@]} / 11 )) # FONT height in characters

function figletise() {
  read str;
  for (( line = 0; line < FONT_HEIGHT; line++ )); do
    printf "  "
    for (( c=0; c<${#str}; c++ )); do
      local ch=$(LC_CTYPE=C printf '%d' "'${str:$c:1}") # get ascii value
      ch=$((ch-48))
      if (( ch >= 0 && ch <= 10 )); then
        local i=$(( ch * FONT_HEIGHT + line )) # 2D -> 1D array conversion
        printf '%s' "${FONT[$i]}"
      fi
    done
    printf "\n"
  done
}

stty -echo 2>/dev/null
printf '\033[?25l\n' # hide cursor
unset EXIT_

while true; do
  date +"$TIME_FORMAT" | figletise
  
  [[ -z $EXIT_ ]] || exit 0
  read -t $REFRESH_INTERVAL -n 1 && EXIT_=1; # bloat for freebird

  printf "\033[${FONT_HEIGHT}A\r" # move cursor to beginning,
                                  # fixed for crappy terminals
done

bashclock

Most of it is quite simple, but there are two interesting things about it (in my opinion):

  1. the escape sequence \033[F which works a bit like the carriage return \r from the progress bar script above, but in addition, moves the cursor one line up
  2. the way of obtaining ASCII code of a character, using printf function and a single quote character – a rather insane syntax which I haven’t seen before, but it works. Read about it here: http://mywiki.wooledge.org/BashFAQ/071
12 Likes