Core Development · Scripting

A Pure Bash Wait Bar: make your Wait Time a fancy time

BashProgressBar

Example of Bash Progress Bar

Problem

How many times did you feel that something was not happening? Or simply, that your wait was not controllable? Such scenario happens systematically whenever in one of the Bash scripts used to automate tasks, a wait time is not properly represented, or even displayed: processes stop their output silently, and… what is the reason? Even if it is a needed wait, the final user may not know and, for example, can think to abort the script – apparently hanging.

 

Solution

The solution is very simple: a progress bar to make the wait fancy, but, controllable at the same time. A naive implementation in Bash looks like the below one: ‘#’ is the symbol picked to represent any progress.

 $ ./run-scenario.sh
 setup: install dependencies: JDK7
 openjdk version "1.8.0_45"
 OpenJDK Runtime Environment (build 1.8.0_45-b13)
 setup: already installed
 setup: install dependencies: XTERM
 xterm is /usr/bin/xterm
 setup: already installed
 setup: install dependencies: TCPDUMP
 tcpdump is /usr/sbin/tcpdump
 setup: already installed
 setup: LIB_PATH=/tmp/dane-demonstrators
 xterm: cannot load font '-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1'
 wait: status: [#####] (100%)
 xterm: cannot load font '-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1'
 wait: status: [##########] (100%)

Source Code

Hereafter, the Bash source code that implements the above progress bar. The code does not have any optimization, it is just demonstrative to let any experienced user to grasp the ideas.

 
#!/usr/bin/env bash

# indicates 100%, as reference
TOT=100
# number of elements in the progress bar
ITR=10
# number of seconds to wait for
SEC=120

# counters
CNT=0
CUR=0

# for simplicity, adapts the elements to the number of seconds if they are a few
if [ $SEC -lt $ITR ];
then
   ITR=$SEC
fi

# a bunch of math
let SYM=ITR
let INC=TOT/ITR
let SPN=SEC/ITR

# prepares body and head of a printable line
HEAD='wait: status: ['
BODY=''
# main loop, it loops over the number of elements in the progress bar
while [ $CNT -le $ITR ];
do
   BODY=''

   # defines how many elements to put into the bar
   POUNDS=0
   while [ $POUNDS -lt $CNT ];
   do
       BODY="$BODY#"
       let POUNDS=POUNDS+1
   done

   # defines how many blank spaces to append
   let BLANKS=SYM-CNT
   while [ $BLANKS -gt 0 ];
   do
       BODY="$BODY "
       let BLANKS=BLANKS-1
   done

   # defines the line tail with the progress percentage
   TAIL="] ($CUR%)"
   echo -ne "$HEAD$BODY$TAIL\r"
   let CUR=CUR+INC
   let CNT=CNT+1

   # spins before of the next update in case its needed
   SPIN=$SPN
   while [ $SPIN -gt 0 ];
   do
       sleep 1
       let SPIN=SPIN-1
   done
done

# fixes any approximation caused by the integer arithmetic
if [ $CUR -ne 100 ];
then
 TAIL="] (100%)"
 echo -ne "$HEAD$BODY$TAIL\r"
fi

echo ''

 

Discussion

The main idea consists in regenerating dynamically the progress bar, displaying it on the same line will give the user a progressive effect of filling up. The first two nested loops in the main loop take care to create the ‘#’s to indicate progress, and the buffering ‘ ‘s to be appended: an example, progressively, [#    ], [##   ], [###  ], given 5 iterations (i.e. elements of the bar) to be controlled with a percentage of increment of about 20%; last loop allows to spin before the successive increment, in case of wait time greater than 100 seconds: as per above, 120 seconds will be rendered within a progress bar of 10 elements, so each increment should be about each 12 seconds (i.e. new ‘#’s will appear each 12 seconds).

Interesting is the echoing technique. As said, the main idea is to stay inline on the same line, so to achieve that the ‘echo’ has been used combining the options ‘-n’ and ‘-e’ that allows to not go on a new line and to interprets any escaped symbol in the string.

 

Conclusion

This post aims at providing a quick solution to a recurrent problem in automation tasks. The code is for demonstrative purpose: optimizations might e done, of course.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s