in reply to Re: File::Find finding . and ..
in thread File::Find finding . and ..

Thanks for the tip, however it is still traversing ..

video/../temp/media/music any ideas?

foreach(@the_wicked){sleep(0);}

Replies are listed 'Best First'.
Re^3: File::Find finding . and ..
by Anonymous Monk on Jul 15, 2009 at 16:02 UTC
    What is it? Show your new code.
      #!/usr/bin/perl use warnings; use strict; use File::Rename qw(rename); use File::Find; our $VERSION = '0.1.3'; ### NAME NORMALIZER ### my @torename = (); my @dirs = (); my $DIR = shift @ARGV; opendir(TOCLEAN, "$DIR") or die $!; @dirs = sort readdir(TOCLEAN); @dirs = map { $_ = $DIR . $_ } @dirs; find(\&cleanup, @dirs); sub cleanup{ return if !stat; my $name = $File::Find::name; my $dir = $File::Find::dir; next if ($name eq '.' or $name eq '..'); if(/[^a-zA-Z0-9_\-\/\.~]/){ print "$name\n"; push(@torename, "$name"); } } if(@torename > 0){ print "Renaming files now..\n"; sleep 1; rename @torename, sub { s/[^a-zA-Z0-9_\-\/\.~]/_/g }, 1; } else{print "No files found to rename.. Exiting\n"};
      foreach(@the_wicked){sleep(0);}
        I wrote return if... and not next if ... for a reason.

        Since you are in a subroutine and not directly in a loop, next will jump to the next iteration of your caller's loop, and warns about Exiting subroutine via next at ... - don't you get such warnings? Since you don't know how File::Find works internally, that might cause very nasty behaviour.

        By the way I don't find that excessive use of newlines improves readability - on the contrary, you have to scroll more to see a relevant part of the code.

        Why are you using opendir/readdir to get the list of files in $DIR? Why not just pass $DIR to find and let that function find all of the files?

        I don't see how you're getting paths that include '/../'. I don't think that readdir will return them. Perhaps I'm missing some obscure symlink usage.

        I'm also surprised that you're not getting a 'Can't "next" outside a loop block' or 'Exiting subroutine via next' error as your next if line should surely be return if.

        If it's really necessary (and I don't think it is) then you could add another line that matches the problematic paths.

        return if m[/\.\./];
        --

        See the Copyright notice on my home node.

        Perl training courses

Re^3: File::Find finding . and ..
by transiency (Sexton) on Jul 15, 2009 at 18:48 UTC
    Got it. if($name !~ /\/\.\.?\//) was the trick that worked.

    Thanks for the help everyone.

    #!/usr/bin/perl use warnings; use strict; use File::Rename qw(rename); use File::Find; our $VERSION = '0.1.4'; ### NAME NORMALIZER ### $|++; my (@dirs, @torename) = (); my $DIR = shift @ARGV; opendir(TOCLEAN, "$DIR") or die $!; @dirs = map { $_ = $DIR . $_ } sort readdir(TOCLEAN); find(\&cleanup, @dirs); if(@torename > 0){ print "Renaming files now..\n"; sleep 1; rename @torename, sub { s/[^a-zA-Z0-9_\-\/\.~]/_/g }, 1; } else{ print "No files found to rename.. Exiting\n" } sub cleanup{ return if !stat; my $name = $File::Find::name; my $dir = $File::Find::dir; next if ($name eq '.' or $name eq '..'); if($name !~ /\/\.\.?\//){ if(/[^a-zA-Z0-9_\-\/\.~]/){ print "Found: $name\n"; push(@torename, "$name"); } } }
    foreach(@the_wicked){sleep(0);}