[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
- [Help-bash] progress bar in bash,
Paolo Supino <=