Wget like progress bar in console

Some time ago I was writing about notifying user that our software does not hang out, today I will also write about this. It is easy to create progress bar, and there is a numerous modules done (Oreily.com). But creating a simple progress bar (which looks like progress bar in wget) is pretty straight forward.

Output with detailed progress

Warning: This is only example after each execution of progressBar "\n" is inserted!. In final code this will be one animating line!
johny@jambia:~$ perl pgbar.pl 
Starting Hello
[i] Hello |>                                                                     | 0 of 10 (  0%)
[i] Hello |======>                                                               | 1 of 10 ( 10%)
[i] Hello |=============>                                                        | 2 of 10 ( 20%)
[i] Hello |====================>                                                 | 3 of 10 ( 30%)
[i] Hello |===========================>                                          | 4 of 10 ( 40%)
[i] Hello |==================================>                                   | 5 of 10 ( 50%)
[i] Hello |=========================================>                            | 6 of 10 ( 60%)
[i] Hello |================================================>                     | 7 of 10 ( 70%)
[i] Hello |=======================================================>              | 8 of 10 ( 80%)
[i] Hello |==============================================================>       | 9 of 10 ( 90%)
[i] Hello |=====================================================================>|10 of 10 (100%)

Hello started

Output normal process bar

Warning: This is only example after each execution of progressBar "\n" is inserted!. In final code this will be one animating line!
johny@jambia:~$ perl pgbar.pl 
Starting Hello
[i] Hello |>                                                                             | (  0%)
[i] Hello |=======>                                                                      | ( 10%)
[i] Hello |===============>                                                              | ( 20%)
[i] Hello |=======================>                                                      | ( 30%)
[i] Hello |==============================>                                               | ( 40%)
[i] Hello |======================================>                                       | ( 50%)
[i] Hello |==============================================>                               | ( 60%)
[i] Hello |=====================================================>                        | ( 70%)
[i] Hello |=============================================================>                | ( 80%)
[i] Hello |=====================================================================>        | ( 90%)
[i] Hello |=============================================================================>| (100%)

Hello started

Usage of my subroutine

I have created subroutine, which helps me display progress of work done by script in simple way. Usage is also pretty straight forward, I think:
my $MAX_I = 10;
my $PROC_NAME="Hello";
print "Starting ".$PROC_NAME."\n";
for ( my $i=0 ; $i<=$MAX_I ; $i++) {
 print progressBar($PROC_NAME, $i, $MAX_I);#."\n";
 sleep 1;
}
print "\n".$PROC_NAME." started\n";

Source of subroutine progressBar

# wget-style progress bar subroutine
#
# Author: Tachyon (http://tachyon.perlmonk.org/)
# Modified: sinx (http://blog.0x1fff.com/)
# 
# Changes: Made usage of original subroutine 
#          more user friendly.
#
sub progressBar {
    my ( $info, $curr, $total ) = @_;

    $info = '[i] ' . $info.' ';
    my @termSize = split( /\s+/, qx{stty size} );

    # Use this if you want detailed process progress
    # my $proc     = sprintf( '%'.length($total).'s of %s (%3d%%)',
    #    $curr, $total, 100 * $curr / +$total );
    my $proc     = sprintf( ' (%3d%%)', 100 * $curr / +$total );
    
    # Add 3 for spaces "\r\n\s" and other
    my $barWidth = $termSize[1] - ( length($info) + length($proc) +3 );
    #$barWidth = 0 if $barWidth < 0; # something is wrong if < 0;
    my $bar = sprintf( "|%-${barWidth}s|",
        '=' x ( ( $barWidth - 1 ) * $curr / $total ) . '>' );

    return $info . $bar . $proc . "\r";
}

Features

  • Upon terminal resize, the screen will not be correctly repainted until the next scheduled update.

Bugs

  • If screen is smaller than "info" and percentage count - it will broke - screen size is not checked in this subroutine

Alternatives - lib-notify

If you are using Gnome environment, you can also notify user about finished jobs using libnotify. Getting lib-notify: apt-get install libnotify-bin.

Sending notify through libnotify

Warning: In Perl you have to invoke system() or qx{}
notify-send -u normal 
  -i /usr/share/icons/gnome/scalable/status/sunny.svg
  'Hello '${USER}', today will be fine day!'
Sample notification looks like this: More detailed instruction about lib-notify can be found in LinuxJournal

Alternatives - progress without percentage

This can be done very easily, I have discussed this in one of my previous blog posts - post and example is in polish and was created for C Programming Language, but code should be very easy to understand even if you don't know polish language.

Comments

Popular posts from this blog

How to generate user documentation from Perl script?

35 Google open-source projects that you probably don't know

Using perl to extract files from large directory structure