Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux Bash iterate over folder with a progress bar

I am writing a little script to process folders. The runtime time is quite long so I would like to add a progress bar.

Here is the iteration :

for file in */
do 
    #processing here, dummy code
    sleep 1
done

Having a counter and knowing the number of folders would be a solution. But I am looking for a more generic and a shorter solution...

I hope someone would have an idea. Thank you for your interest,

Julien

Edit :

I get this solution which do what I want, and is really graphical :

#!/bin/bash
n_item=$(find /* -maxdepth 0 | wc -l)
i=0
for file in /*
do
    sleep 1 #process file
    i=$((i+1))
    echo $((100 * i / n_item)) | dialog --gauge "Processing $n_item folders, the current is $file..." 10 70 0
done

However, I will keep fedorqui 's solution which doesn't take all the screen.

Thank you very much for your time

like image 981
j.flajo Avatar asked Sep 27 '13 08:09

j.flajo


3 Answers

Based on the results we posted in How to print out to the same line, overriding previous line? I came with this result:

#!/bin/bash

res=$(find /* -maxdepth 0 | wc -l)
echo "found $res results"
i=1

for file in /*
do
    echo -n "["
    for ((j=0; j<i; j++)) ; do echo -n ' '; done
    echo -n '=>'
    for ((j=i; j<$res; j++)) ; do echo -n ' '; done
    echo -n "] $i / $res $file" $'\r'
    ((i++))
    sleep 1
done

Example

$ ./a
found 26 results
[  =>                        ] 2 / 26 /boot 
[                =>          ] 16 / 26 /root
like image 176
fedorqui 'SO stop harming' Avatar answered Nov 16 '22 18:11

fedorqui 'SO stop harming'


Based on fedorqui's amazing solution I made a function which works really well with any loop.

function redraw_progress_bar { # int barsize, int base, int i, int top
    local barsize=$1
    local base=$2
    local current=$3
    local top=$4        
    local j=0 
    local progress=$(( ($barsize * ( $current - $base )) / ($top - $base ) )) 
    echo -n "["
    for ((j=0; j < $progress; j++)) ; do echo -n '='; done
    echo -n '=>'
    for ((j=$progress; j < $barsize ; j++)) ; do echo -n ' '; done
    echo -n "] $(( $current )) / $top " $'\r'
}

So you can easily do for loops like

for (( i=4; i<=20 ; i+=2 ))
do
    redraw_progress_bar 50 4 $i 20
    $something $i
done
echo $'\n'
like image 44
brunch875 Avatar answered Nov 16 '22 16:11

brunch875


If you want a graphical progress bar (GTK+), have a look at zenity :

#!/bin/bash
(
    for i in {0..5}
    do
        echo $((i*25))
        echo "#Processing $((i+1))/5"
        sleep 1
    done
) | zenity --progress --width=400 --title="Please wait" --auto-close
like image 3
Junior Dussouillez Avatar answered Nov 16 '22 18:11

Junior Dussouillez