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

O Monks, I ask this of you:

I am trying to recursively traverse a subweb that I moved from a FrontPage-based server to one that isn't. In the process, I want to blow away all of the _vti_cnf directories in this subweb. Consulting the Perl Cookbook, I came up with what I thought was the solution:

#!/usr/bin/perl use File::Find; use File::Path; @ARGV = qw(.) unless @ARGV; sub process_file { ((-d _) && /_vti_cnf/) && rmtree $File::Find::name; } find (\&process_file, @ARGV);
When run in the root of the subweb I wanted to process with no arguments, though, it only deleted the _vti_cnf directory in the root itself, and not any of the subdirectories like I wanted. What could I be doing wrong?

Replies are listed 'Best First'.
•Re: Recursively blowing away directories of a certain name
by merlyn (Sage) on Nov 26, 2003 at 17:35 UTC
    I wouldn't delete during the traversal. I'd save all the names and delete afterwards:
    use File::Find qw(find); use File::Path qw(rmtree); @ARGV = qw(.) unless @ARGV; my @goners; find sub { return unless -d; return unless $_ eq "_vti_cnf"; $File::Find::prune = 1; # don't descend, gone later anyway push @goners, $File::Find::name; }, @ARGV; rmtree \@goners, 1, 1; # trace, and ignore undeleteables

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

      Awesome. This worked like a charm, of course. Thanks so much!
Re: Recursively blowing away directories of a certain name
by Aristotle (Chancellor) on Nov 26, 2003 at 18:03 UTC
    use File::Find::Rule; use File::Path; rmtree [ File::Find::Rule ->directory() ->name( '_vti_cnf' ) ->prune() ->in( @ARGV ) ];
    Update: added prune() per runrig's suggestion.

    Makeshifts last the longest.

Re: Recursively blowing away directories of a certain name
by dragonchild (Archbishop) on Nov 26, 2003 at 19:34 UTC

    Don't use Perl if something else can do it better. A shell example could be:

    rm -rf $(find . -type d -name '_vti_cnf')

    ------
    We are the carpenters and bricklayers of the Information Age.

    The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

    ... strings and arrays will suffice. As they are easily available as native data types in any sane language, ... - blokhead, speaking on evolutionary algorithms

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      If we're doing shell script, we might as well make it robust. Your solution is probably the simplest way, and will work most of the time, but will blow up if there're too many directories to fit on one command line. xargs solves this nicely:

      find . -type d -name '_vti_cnf' | xargs rm -rf

      Or, if there are funky characters in the directory names, a while read loop is what I would use:

      find . -type d -name '_vti_cnf' | while read dir ; do rm -rf "$dir" ; done