On Tue, Nov 18, 2014 at 05:46:15PM -0500, Harry Putnam wrote:
> #!/usr/bin/perl
> 
> use strict;
> use warnings;
> 
> if (!@ARGV) {

Alternatively to the @ARGV == 0 suggested by others, there's
always:

  unless(@ARGV) { ... }

It's a matter of taste. Nothing really wrong with !@ARGV.

>   usage();
>   print "At least one directory name is required\n";
>   print "Usage tripped: line: <" . __LINE__ . ">\n";
>   exit;
> } elsif ($ARGV[0] eq "help") {
>   usage();
>   print "Usage tripped: line: <" . __LINE__ . ">\n";
> }
> 
> my $myscript;
> ($myscript = $0) =~ s/^.*\///;
> 
> ## BEGIN GETOPTS SECTION =========================================
> # [HP 12/03/07_20:31:55 Don't use `use vars' anymore ] 
> our ($opt_f);
> use Getopt::Std;
> my $optstr = "f";
> getopts($optstr);

It's strange that you're using a Getopt module, but above are
checking for $ARGV[0] eq "help" explicitly. In general, I'd
prefer to see all of the argument parsing happenig at once. And
--help is more standard than merely "help" (there may well be a
file/directory called help).

> my $FORCE; # expects boolean content

If it's meant to be a boolean then I would initialize it as such.
The all-caps seems unnecessary as well.

my $force = 0;

> if($opt_f) { ## force unlink ... no ask
>   $FORCE = 'TRUE';

'TRUE' is misleading in the case of a boolean variable because
'FALSE' will still be interpretted as true. You're better off
using actual boolean values in Perl (e.g., 0 and 1).

Additionally, since you are already counting on $opt_f being a
boolean you might as well just copy it instead of branching on
its value. No need for the if statement.

my $force = $opt_f;

> }

I'm not sure how that $opt_f got filled in, but I'm assuming it
is how Getopt::Std works.. In this case I'm not sure I see a need
to copy the value (you could just use $opt_f), but then I'm not
familiar with Getopt::Std. There are alternative Getopt:: modules
that may behave more cleanly. I know that Getopt::Long works
quite nicely and is fully-featured.

> my @trgs = @ARGV;
> @ARGV = ();
> for (@trgs) {
>   if (! -d) {
>     print "Whoops, no directory <$_> found on system .. skipping\n";
>     my $ditchme = shift @trgs; # Get rid of non-starters
>     $ditchme = ''; ## zero it out ??

Zero what out? Assigning the empty string to a variable does not
"zero it out". It merely changes what that variable contains.
It's a lexical variable inside of the loop though so it would
lose its content as soon as the loop iterates again. I suspect
that the shift is erroneous as well, but I believe Rob already
showed you a better way to do this so I'll leave it alone.

>   }
> }
> 
> use File::Find;
> use Cwd 'abs_path';
> 
> find(
>      sub  {
>        return unless -f;
>         my $file = $_;
>         my $abs_path = abs_path($file);

I believe that File::Find::name always contains the absolute path
so I see no need to use abs_path() here..

>         if (/~$|\#|\.sw[po]$/) {

I don't know how accurate this definition is so I won't criticise
it, but it does look like a good use for a CPAN module so I
would encourage you to check and see if such a thing has already
been defined better by searching metacpan.org.

>           if (! $FORCE) {
>             print "\\FOUND: <$abs_path>\n",
>                   " Shall we unlink <delete> it? <y/n> ";
>             my $ans = <STDIN>;
>             if ($ans =~ /^y$/) {
>               unlink $abs_path  or die "Can't unlink <$abs_path>: $!";
>               printf "%-60s %s\n","<$abs_path>", "unlinked";
>               ## We need to use $_ rather than $File::Find::name because
>               ## The latter doesn't work in all situations.  And since the
>               ## File::Find program is recursing right along with the search
>               ## $_ will always work

I'm not sure what this comment is about since there appears to be
no code coming after it, and the code immediately before it isn't
using $_, but I'm not sure the comment is accurate either.

>             } else {
>              printf "%-60s %s\n", "<$abs_path>", "skipped"
>            }
>          } else {
>            unlink $abs_path  or die "Can't unlink <$abs_path>: $!";
>            printf "%-60s %s\n", "<$abs_path", "unlinked";

Rather than duplicating this code I'd rather see it restructured
to reuse the same code. This is essentially the "we have
confirmation, delete the file" code. That can either be put into
a separate function, or the want subroutine can be restructured.
While we're reformatting we could also put the definition of what
constitutes an editor backup file into a separate subroutine to
break this one down into as many pieces as possible. Your use of
printf is a little bit weird too. Passing in string literals and
interpolating when you could have those static parts in the
format string.

For example:

sub confirm_unlink {
    print "Found: <$abs_path>\n",
            "Unlink (delete) it? (Y/n) ";

    my $answer = <STDIN>;

    return $answer =~ /^y/i;
}

sub is_editor_garbage {
    my ($filename) = @_;

    return $filename =~ /~$|\#|\.sw[po]$/;
}

sub report {
    my ($abs_path, $status) = @_;

    # Protip: I'm not sure which is better, interpolating $status
    # into the format string, or passing it as an argument. I'm
    # sure it's negligible in this case.
    printf "<%-60s> $status\n", $abs_path;
}

sub unlink_file {
    my ($abs_path) = @_;

    unlink $abs_path or die "unlink <$abs_path>: $!";

    report($abs_path, 'unlinked');
}

sub wanted {
    return unless -f;

    my $abs_path = $File::Find::name;
    my $filename = $_;

    unless(is_editor_garbage($filename)) {
        return;
    }

    unless($force || confirm_unlink($abs_path)) {
        report($abs_path, 'skipped');

        return;
    }

    unlink_file($abs_path);
}

>          }
>        }
>      }, @trgs
> );

I'd like to see white-space here. White-space is practially free
and spares your eyes and brain a lot of unneeded strain trying to
figure out where one idea ends and another begins. Use lots of
white-space.

> sub usage{
>    print "
>   Purpose: Recurse thru list of directories and search out all editor leavings
>   (some~ .some.swp some.bak etc), but also includes things like #some# or the 
> like.
>   Usage:`$myscript dir1 dir2 ... dirN'
> ";

Consider using a HEREDOC in this case. I might also recommend the
use of printf in a large block of text with a single hidden
variable in it because it's easy to miss.

printf <<EOF, $myscript;
Purpose: Recursve through list of directories and search out all editor leavings
(some~ .some.swp some.bak etc.), but also includes things like #some# or the 
like.
Usage: %s dir1 dir2 ... dirN
EOF

(Untested)

> }

Hope that helps.

Regards,


-- 
Brandon McCaig <bamcc...@gmail.com> <bamcc...@castopulence.org>
Castopulence Software <https://www.castopulence.org/>
Blog <http://www.bamccaig.com/>
perl -E '$_=q{V zrna gur orfg jvgu jung V fnl. }.
q{Vg qbrfa'\''g nyjnlf fbhaq gung jnl.};
tr/A-Ma-mN-Zn-z/N-Zn-zA-Ma-m/;say'

Attachment: signature.asc
Description: Digital signature

Reply via email to