help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Help-bash] progress bar in bash


From: Paolo Supino
Subject: [Help-bash] progress bar in bash
Date: Tue, 22 Jul 2014 10:11:54 +0200

Hi

The following bash code (here it's a complete script, adapted to be self
containing, but in reality it's part of a much bigger script that I'm
supporting) that prints a progress bar (merging a few posts about progress
bars I found on the internet)...

#!/bin/bash

convert_time() {

   local -r time_input=$1
   local regex="^[0-9hms.\ ]+$"

   if [[ $time_input =~ $regex ]]; then

      local -r regex="[0-9.]"
      local -ir hour=3600 minute=60 second=1 char=1

      local current_char="" time_string="" time_in_seconds=""    \
      local num_string="" time_unit=""
      local -i seconds_int=0 time_counter=0 total_seconds=0

      time_string=${time_input// /}
      local -ir time_string_length=${#time_string}

      for
((time_counter=0;time_counter<=time_string_length;time_counter++)); do
         current_char=${time_string:$time_counter:$char}
         if [[ $current_char =~ $regex ]]; then
            num_string="$num_string$current_char"
            continue
         elif [[ $current_char == 'h' ]]; then
            time_unit=hour
         elif [[ $current_char == 'm' ]]; then
            time_unit=minute
         else
            time_unit=second
         fi

         if [[ -n $num_string ]]; then
            time_in_seconds=$(echo "${num_string}*${!time_unit}" | bc)
            seconds_int=${time_in_seconds%%.*}
            total_seconds=$((total_seconds+seconds_int))
            num_string=""
         fi
      done
      echo $total_seconds
   else
      echo "illegal character found, exiting"
      exit 7
   fi
}

init_vars() {

   sleep_interval=0.1
   start_time=$(date +%s)
   elapsed=0
   percent=0
   bold=$(tput bold)
   normal=$(tput sgr0)
}

time_delta() {

   now=$(date "+%s")
   elapsed=$((now-start_time))
}


progress_bar() {

   init_vars

   while [[ $percent -le 100 ]]; do

      local current_screen_width=$(tput cols)
      width=$((current_screen_width-(AppName_length+21)))

      bar_width=$(echo "scale=2;($width/100)" | bc)
      bars_percent=$(printf '%3.1f\n' $(echo
"(($bar_width*$percent)+0.5)/1" | bc))
      bars_percent_int=${bars_percent%%.*}

      printf "\rDeploying %-s " "${bold}${AppName}${normal}"

      printf "["
      for i in $(seq 1 $bars_percent_int); do
         printf "="
      done
      for i in $(seq $bars_percent_int $(( $width-1 ))); do
         printf " "
      done
      printf "] "

      time_delta
      printf "%s%3d%%%s" "${bold}" "${percent}" "${normal}"
      percent=$(( 100 * elapsed / progrss_bar_time ))
      sleep $sleep_interval
      local last_screen_width=$current_screen_width
   done
}

tput civis
AppName=$1
AppName_length=${#AppName}
bar_duration=$2
progrss_bar_time=$(convert_time $bar_duration)
progress_bar
echo -e "\n"
tput cnorm


My problem is that when I make the terminal window screen narrower the bar
goes down 1 (or more lines) and leaves the old drawn progress bar in the
lines above... I tried to fix this by adding the following 2 functions:

row_position() {

   exec < /dev/tty
   oldstty=$(stty -g)
   stty raw -echo min 0
   echo -en "\033[6n" > /dev/tty
   IFS=';' read -r -d R -a pos
   stty $oldstty
   current_row=$(( ${pos[0]:2}-1 ))

   echo $current_row

}
and
calc_bar_width() {

   local -ir colomn=0
   width=$((current_screen_width-(AppName+21)))
   bar_row=$(row_position)
   tput cup $bar_row,$colomn
}

and modifying the standalone script to check if terminal width has changed
to call calc_bar_width() (I didn't include that code)
to make the bar always appear on the same line when I make the window
narrower... but it doesn't work :(

Anyone has suggestions how I can force the script draw the bar on the same
line when I narrow the terminal windows?

This email is a open heart surgery to the progress bar drawing, feel free
to rip it apart as you see fit...




TIA
Paolo


reply via email to

[Prev in Thread] Current Thread [Next in Thread]