in reply to Re: Re: Re: File copy progress.
in thread File copy progress.

Here is quick but cheap way to do it. Im just posting the progress routine but in the main routine you also have to toss the percent variable and instead have a variable keep track of total bytes writen. Then call this sub passing it total_writen, and file size. This routine also uses fastolfe's suggestion of using \r instead of \n so just the line is updated ( works on win2k too!).

sub FileProgress () { my $wrote = shift; my $size = shift; my $percent = $wrote / $size * 100; case: { if ($percent <11) { print "\r[* ]"; last;} if ($percent <21) { print "\r[** ]"; last;} if ($percent <31) { print "\r[*** ]"; last;} if ($percent <41) { print "\r[**** ]"; last;} if ($percent <51) { print "\r[***** ]"; last;} if ($percent <61) { print "\r[****** ]"; last;} if ($percent <71) { print "\r[******* ]"; last;} if ($percent <81) { print "\r[******** ]"; last;} if ($percent <91) { print "\r[********* ]"; last;} if ($percent <=100) { print "\r[**********]"; last;} } printf " %3u",$percent; print '%'; printf " done. %u bytes.",$wrote; return 1; }

zzSPECTREz

Replies are listed 'Best First'.
Re: Re: Re: Re: Re: File copy progress.
by Kanji (Parson) on Dec 06, 2000 at 07:03 UTC

    You probably don't want to be using a prototype of () for this sub as you'll be trying to pass arguments to a sub that (regardless of the shifts inside the sub) doesn't take any!

    You can also simplify things greatly by performing another sum (to get rid of that case: { ... })in combination with a single printf()...

    sub FileProgress { my $wrote = shift; my $size = shift; my $percent = $wrote / $size * 100; printf "\r[%-10s] %3u%% done. %u bytes", '*' x int( $percent / 10 ), $percent, $wrote; return 1; }

        --k.

    Update: Removed the trailing \n.

      Cool!!!! I didnt think of using the repeat operator. Thats what I like about sharing your code here, someone usually allways has a good suggestion about how to do something better or a way to simplify. I had a problem getting the % to work in the printf.. I looked in the camel book and didnt see any example or explanation. I tryed escaping it like \%.. I didnt think of trying %%.

      One minor correction... The trailing \n needs to be removed from printf so that the status is displayed on the same line.

        use warnings; use strict; $| = 1; #sets buffer to immediately flush my $mydir = 'C:\some\path'; my $destination = 'C:\some\other\path'; opendir (MYDIR, $mydir) or die "Could not opendir $mydir: $!\n"; my @files = grep { /\.ext$/} readdir MYDIR; closedir(MYDIR); for (@files) { &CopyFileProgress("$mydir\\$_","$destination\\$_",\&FileProgress); print "\n"; } sub CopyFileProgress ( ) { my $src = shift; my $dst = shift; my $callback = shift; my $num_read; my $num_wrote; my $buffer; my $total_written = 0; open (SRC, "< $src") or die "Could not open source file [$src]: $! +\n"; open (DST, "> $dst") or die "Could not open destination file [$dst +]: $!\n"; binmode SRC; binmode DST; my $filesize = (-s $src) or die "File has zero size.\n"; my $blksize = int ($filesize / 10); while (1) { $num_read = sysread(SRC, $buffer, $blksize); last if ($num_read == 0); die ("Error reading from file [$src]: $!\n") if (!defined($num +_read)); my $offset = 0; while ($num_read){ $num_wrote = syswrite(DST,$buffer,$num_read,$offset); die ("Error writing to file [$dst]: $!\n") if (!defined($n +um_wrote)); $num_read -= $num_wrote; $offset += $num_wrote; $total_written += $offset; } my $filename = basename($src); &$callback($filename, $total_written, $filesize) or die ("Copy + canceled.\n"); } } sub FileProgress { my $filename = shift; my $wrote = shift; my $size = shift; my $percent = $wrote / $size * 100; printf "%s [%-10s] %3u%% done. %5u MBs\r", $filename, '*' x int( $percent / 10 ), $percent, $wrote / 1024 / 1024; return 1; }
        Very nice, thank you!!