in reply to printing a running count

Another technique that it make sense to mention (and figure me if this is "overkill" in your case!), is that of creating a "visual meter".  Here's an example of an object meter, which you can use to manage the display of a progress meter which increments towards a final total.

You simply create the meter object with my $meter = new meter($total), call it within the loop with $meter->update($i), and finish up by calling it with no arguments $meter->update() (to show 100% completion, and display the final newline).

Update:  Added auto-flush of STDERR to the package.

Here's the code:

#!/usr/bin/perl -w + # Strict use strict; use warnings; + + # User-defined my $total = 10_000; + + # Main program my $i; print "Progress (of whatever)\n"; my $meter = new meter($total); for (my $i = 0; $i < $total; $i++) { $meter->update($i); # Call your code here &my_subroutine(); } $meter->update(); print "Done!\n"; + + # Subroutines sub my_subroutine() { # For test purposes, sleep for a random interval of milliseconds my $nmilli = int(rand(1010) / 1000); select(undef, undef, undef, $nmilli); } + + package meter; + # Libraries use Carp; + + # # Inputs: $1 ... the meter object # $2 ... total value (when reached, the meter will register + 100%) # # Description: Creates a "visual" meter, which displays an ascii pic +ture # representing the progress towards a total count. # sub new() { my ($proto, $total) = @_; ($total || 0) or croak "Invalid 'total' in object 'meter'"; + # User-configurable my $width = 64; # Total meter width my $blank = '-'; # Blank symbol my $done = '*'; # Progress symbol + my $interval = int($total / $width); my $class = ref($proto) || $proto; my $self = { 'total' => $total, 'interval' => $interval, 'width' => $width, 'blank' => $blank, 'done' => $done, }; bless $self, $class; $self->update(0); return $self; } + # # Inputs: $1 ... the meter object # $2 ... (optional) the progress count (if undefined, sets +the # count to the total, and outputs the final newline) +. # # Description: Updates the meter using the given count (which should + be # a minimum of zero, and a maximum of $this->{'total'}) +. # sub update() { my ($this, $count) = @_; my $done = defined($count)? 0: 1; my $total = $this->{'total'}; defined($count) or $count = $total; return unless ($count == $total || 0 == ($count % $this->{'interva +l'})); my $pct = 100 * $count / $total; my $width = $this->{'width'}; my $size = int($width * $count / $total); my $str0 = $this->{'done'} x $size; my $str1 = $this->{'blank'} x ($width - $size); select((select(STDERR), $| = 1)[0]); printf STDERR " %6.2f%% [%s%s]\r", $pct, $str0, $str1; $done and print STDERR "\n"; } + 1;