http://qs321.pair.com?node_id=11110753

bigal_george has asked for the wisdom of the Perl Monks concerning the following question:

Hi Ive got a file delete routine which in a loop as each singular file or directory is removed I do this: print STDERR "."; which gives a continuous row of dots progressing across the screen as each file or directory is deleted. using below: use File::Copy::Recursive qw(fcopy rcopy dircopy fmove rmove dirmove); dircopy($a,$b); I have no idea how to write a callback to the dircopy() function, or if its possible. But there are thousands of files, and once the perl script is called seeing a blinking cursor is very non-intuitive and I'd appreciate if anyone could advise how I can simply show the dots progress as per the delete routine. Regards, Al.

Replies are listed 'Best First'.
Re: Super simple progress
by marto (Cardinal) on Dec 30, 2019 at 09:06 UTC
Re: Super simple progress (Twirling baton alternative)
by jcb (Parson) on Dec 31, 2019 at 00:53 UTC

    The "twirling baton" is another simple progress indicator that may be more suited to large jobs with indeterminate ends. Here's a simple implementation that I wrote years ago, long before even finding this site:

    BEGIN { my @chars=('-','\\','|','/','-','\\','|','/'); my $step=0; sub baton_start { $step=0 ; goto &baton_step } sub baton_step { print STDERR $chars[$step++],"\b"; $step=0 if $step >=8 } sub baton_end { print STDERR "\b "; } }

    I have used this in many one-off scripts and I generally just copy and paste it when needed, since it is so simple.

      Not on windows you havent :) \r\r\r\r\r\r\r\r\r\r\r\r

        You are correct about that; none of my personal stuff has been on Windows for over a decade now. Come to think of it, none of the "heavy lifting" at $WORK has been on Windows either.

        I presume the builtin Windows excuse for a terminal emulator does not properly handle ASCII backspace and overwrite? Have you tried rxvt or other ports of X11-native terminal emulators that actually work? There is even a MinGW X server if I recall correctly, so you could use xterm on Windows. :)

Re: Super simple progress
by davido (Cardinal) on Dec 30, 2019 at 16:45 UTC

    Out of curiosity, how will you know the file count ahead of time so that you can present a meaningful progress bar?


    Dave

      Hi there. Its not important; and just another distraction waiting for the system to work out initial state. Thats why I simply printed a contiguous series of dots - the user knows each dot is file progress (also I add a directory print each time one of those is deleted).

        Fair enough, so you need a sort of "I'm still doing something" row of dots that emerges as work progresses.

        It's a little unfortunate how File::Copy::Recursive implements recursion in dircopy. I mean it works great, but it's hard to hook into. However, the dircopy subroutine calls fcopy which is easier to wrap. So this seems to work as I had hoped:

        #!/usr/bin/env perl use strict; use warnings; use File::Copy::Recursive qw(dircopy); use Hook::WrapSub qw(wrap_subs); use IO::Handle; sub after_dircopy { print '.'; STDOUT->flush; } wrap_subs sub {}, 'File::Copy::Recursive::fcopy', \&after_dircopy; dircopy('/tmp/test1', '/tmp/test2'); print "\n";

        I'm wrapping the fcopy function, which dircopy calls by adding a sub that fires off after each fcopy call. The wrapper prints a dot and flushes STDOUT.

        One warning: This depends on an implementation detail of dircopy. There are no guarantees the module's author couldn't change how dircopy works, rendering this broken.


        Dave

Re: Super simple progress
by bigal_george (Acolyte) on Dec 30, 2019 at 08:23 UTC
    Just thinking about it a bit more, I guess an onscreen timer instantiated before the dircopy() routine would do the trick, but its kind of nice to see those dots zipping along. Advantage of a timer would be its still showing activity, and the end result could show the total time taken along with accrued files and directories copied or moved. Thanks. Al.