10

I'm using the following script to go through a large list of domains in whois and find the registrar (useful for server/DNS migrations) and it works fine.

However I am wanting to incorporate a progress bar into it just for the sake of convenience. Here's my script, if it can be improved let me know:

#!/bin/bash
for f in `cat /var/www/vhosts/domainlist`
 do
   if
   domain=$f
   [ "$domain" ] ;
   then
    whois $f | grep -i domainregistrar > /dev/null
     if
     [ $? -le 0 ] ;
     then
      echo $f >> our_registrar
     else
      echo $f >> external_registrar
     fi
   fi
 done
echo "Done, check our_registrar file."

I've tried this first: http://moblog.bradleyit.com/2010/02/simple-bash-progress-bar-function.html

And then this but with no luck.

What do you reckon is the easiest way to get a progress bar implemented into that script?

Zippyduda
  • 107
  • 2
  • 7
  • 19

6 Answers6

15

Here's a fancy progress bar that you might enjoy...

#!/bin/bash
#   Slick Progress Bar
#   Created by: Ian Brown (ijbrown@hotmail.com)
#   Please share with me your modifications
# Functions
PUT(){ echo -en "\033[${1};${2}H";}  
DRAW(){ echo -en "\033%";echo -en "\033(0";}         
WRITE(){ echo -en "\033(B";}  
HIDECURSOR(){ echo -en "\033[?25l";} 
NORM(){ echo -en "\033[?12l\033[?25h";}
function showBar {
        percDone=$(echo 'scale=2;'$1/$2*100 | bc)
        halfDone=$(echo $percDone/2 | bc) #I prefer a half sized bar graph
        barLen=$(echo ${percDone%'.00'})
        halfDone=`expr $halfDone + 6`
        tput bold
        PUT 7 28; printf "%4.4s  " $barLen%     #Print the percentage
        PUT 5 $halfDone;  echo -e "\033[7m \033[0m" #Draw the bar
        tput sgr0
        }
# Start Script
clear
HIDECURSOR
echo -e ""                                           
echo -e ""                                          
DRAW    #magic starts here - must use caps in draw mode                                              
echo -e "          PLEASE WAIT WHILE SCRIPT IS IN PROGRESS"
echo -e "    lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk"  
echo -e "    x                                                   x" 
echo -e "    mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj"
WRITE             
#
# Insert your script here
for (( i=0; i<=50; i++ ))  
do
    showBar $i 50  #Call bar drawing function "showBar"
    sleep .2
done
# End of your script
# Clean up at end of script
PUT 10 12                                           
echo -e ""                                        
NORM

looks like this:

looks like this

rubo77
  • 19,527
  • 31
  • 134
  • 226
Ian Brown
  • 151
  • 1
  • 2
  • I get a strange unicode-sign at the top-left corner for the %: `% PLEASE WAIT WHILE SCRIPT IS IN PROGRESS` how can I remove that? screenshot: http://i.stack.imgur.com/7JHnj.png – rubo77 Sep 30 '13 at 09:48
  • 1
    I think I solved it with changing DRAW to just `DRAW(){echo -en "\033(0";}` What was the `echo -en "\033%";` for? – rubo77 Sep 30 '13 at 10:36
  • 1
    Can you please explain this solution? – Shammel Lee Jun 24 '17 at 23:02
7

You can use pv but the other way.

 for ... # outer loop
 do
   ...
   echo -n X
 done | pv -s $(wc -l 'your_file_list') - >/dev/null 

so you use echo X to say when another portion of work is done and this is counted by pv, it's know what the whole job size is due to -s option.

nshy
  • 1,074
  • 8
  • 13
  • I shall have a look at this when I get home :) Cheers so far. – Zippyduda Jul 21 '12 at 16:15
  • This is pretty neat, but bear in mind that it puts the for-loop in a subshell, and so any changes you make to variables inside the loop won't affect variables outside the loop! – Jon Gjengset Dec 04 '13 at 13:55
3

You could use something like:

progress(){
    # example usage:
    # progress 30G 9G 30
    # 30G [================>.................................] 30% (9G)

    # params:
    # $1 = total value (e.g.: source size)
    # $2 = current value (e.g.: destination size)
    # $3 = percent completed
    [[ -z $1 || -z $2 || -z $3 ]] && exit  # on empty param...

    percent=$3
    completed=$(( $percent / 2 ))
    remaining=$(( 50 - $completed ))

    echo -ne "\r$1 ["
    printf "%0.s=" `seq $completed`
    echo -n ">"
    [[ $remaining != 0 ]] && printf "%0.s." `seq $remaining`
    echo -n "] $percent% ($2)  "
}

from https://gist.github.com/ivanalejandro0/9159989

You can see an usage example in https://github.com/ivanalejandro0/misc/blob/master/shell-scripts/copy-progress.sh

ivanalejandro0
  • 1,689
  • 13
  • 13
1

Change the outer loop to:

pv /var/www/vhosts/domainlist | while read f
do
    ...
done

http://linux.die.net/man/1/pv

Or you can use any other program that provides a progress bar based on how much a file has been read.

Dunes
  • 37,291
  • 7
  • 81
  • 97
  • I placed that line in it, the script still works however it goes to 100% with the bar full immediately: ./findregistrar.sh 1.12kB 0:00:00 [30.4MB/s] [===============================================================================‌​===================>] 100% so it has not worked correctly. It sits at the blank cursor which is normal until completed, then when done obviously it says: Done, check our_registrar file. But not clear on why it is not working. – Zippyduda Jul 21 '12 at 15:05
  • I have a feeling it is due to it not knowing what 25/50/75/100 is actually defined by and when it has reached a % stage. – Zippyduda Jul 21 '12 at 15:12
  • 1
    It's probably because bash's read read whole input and then process it. – nshy Jul 21 '12 at 15:55
  • Would it help if I got it to calculate how many lines are in the file, divide this by 10 and tell it when =>X (or <=X ) amount of lines has completed, that is 10% and do a line count/check and then once it has completed each line get it to say "complete". – Zippyduda Jul 21 '12 at 16:15
1

Given that you mentioned in a comment that you're on a debian based system, you could use whiptail. When you install a deb package that requires configuration, text-based windows are drawn to ask you stuff; that's whiptail.

Something like

#!/usr/bin/env bash

# mapfile requires bash 4
mapfile -t domains < /var/www/vhosts/domainlist

# for older bash versions, read can be used in this case.
#IFS=$'\n' read -rd '' -a domains < /var/www/vhosts/domainlist

n=${#domains[@]}

for ((i=0; i < n; ++i)); do
    printf 'XXX\n\n%s\nXXX\n' "Checking ${domains[i]}"
    if whois "${domains[i]}" | grep -Fiq domainregistrar; then
        printf '%s\n' "${domains[i]}" >&3
    else
        printf '%s\n' "${domains[i]}" >&4
    fi
    printf '%d\n' $((100*i/n))
done 3>our_registrar 4>external_registrar | whiptail --gauge "" 6 50 0
geirha
  • 5,801
  • 1
  • 30
  • 35
0

I suggest you to use Xdialog, Kdialog or zenity and it's progress option.

igustin
  • 1,110
  • 8
  • 8
  • Forgot to say, (not sure if relevant), on an Ubuntu 10.04 box with only SSH, no GUI. Those seem directed towards ones with a GUI, however I imagine due to it being unix it all applies down to SSH anyway. – Zippyduda Jul 21 '12 at 13:34
  • OK, then the pv is optimal solution. – igustin Jul 21 '12 at 14:15