Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Recursive search and delete

by qwerty80 (Initiate)
on Nov 16, 2012 at 06:26 UTC ( #1004138=perlquestion: print w/ replies, xml ) Need Help??
qwerty80 has asked for the wisdom of the Perl Monks concerning the following question:

Hello All, I m trying to search for a particular *.xml files and then delete it from a directory. following code is throwing me an error. help me..
#!/usr/bin/perl use strict; my $file = "abc*.xml*"; my $searchdir = "/tst"; readDirectory($searchdir, $file); sub readDirectory { my $searchdir = shift; my $searchfile = shift; print "Searching in $searchdir \n"; # Open and close the directory opendir DIR, $searchdir or die("An error occured: $!"); my @files = readdir(DIR); closedir DIR; foreach my $currentFile (@files) { next if $currentFile =~ /^\./; if ( $currentFile eq $searchfile ) { print "Found the file: $searchdir/$curre +ntFile n"; unlink($file); } if ( -d "$searchdir/$currentFile" ) { readDirectory("$searchdir/$currentFile", $searchfile); } } }

Comment on Recursive search and delete
Download Code
Re: Recursive search and delete
by NetWallah (Abbot) on Nov 16, 2012 at 06:53 UTC
    Please use <code> tags to preserve format for your code </code>.

    Your statement:

    if ( $currentFile eq $searchfile )
    Looks for an exact string match between the $currentFile and "abc*.xml*".

    It is unlikely to find a file with that name.
    You could use regular expressions to match the file name, but I would recommend re-designing your code around the File::Find module and friends (File::Find::Match).

                 "By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest."           -Confucius

Re: Recursive search and delete
by tobyink (Abbot) on Nov 16, 2012 at 09:36 UTC

    The error is as NetWallah says, that you are checking to see if the filename equals "abc*.xml*" - not if the filename matches that pattern.

    Personally I'd use Path::Class::Rule...

    # untested! use strict; use warnings; use Path::Class::Rule; my $rule = Path::Class::Rule->new->file->name("abc*.xml*"); $_->remove for $rule->all("/tst");
    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
Re: Recursive search and delete
by Tommy (Chaplain) on Nov 16, 2012 at 10:06 UTC

    Untested:

    use File::Util; unlink for grep { $_ =~ /xml$/i } File::Util->new->list_dir('/your/directory', '--recurse');

    Or alternately:

    use File::Util; $f = File::Util->new(); unlink for grep { $_ =~ /xml$/i } $f->list_dir('/your/directory', '--r +ecurse');
    --
    Tommy
    $ perl -MMIME::Base64 -e 'print decode_base64 "YWNlQHRvbW15YnV0bGVyLm1lCg=="'
Re: Recursive search and delete
by zentara (Archbishop) on Nov 16, 2012 at 10:54 UTC
    And a File::Find example: ( the regex probably needs improvement :-) )
    #!/usr/bin/perl # delete all of the *.xml* files recursively use File::Find qw(find); @ARGV = qw(.) unless @ARGV; find sub { return unless -f; return unless $_ =~ /(.*).xml(.*)/; unlink $_ and warn "deleted $_\n"; }, @ARGV; # it would be good to show all dirs to be deleted # and promp user for 'yes' __END__

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: Recursive search and delete
by roboticus (Canon) on Nov 16, 2012 at 11:16 UTC

    qwerty80:

    You already have several good answers, so I'm not really adding much. However, I've not played much with opendir or readdir and I thought I'd like to play with them a bit. I didn't want a recursive solution, so I did it this way:

    $ cat 1004138.pl #!/usr/bin/perl use strict; use warnings; use 5.10.0; use autodie; my $filespec = "abc*.xml"; my @dirs = ('ABC'); while (@dirs) { my $curdir = pop @dirs; opendir(my $dh, $curdir); for my $f (readdir($dh)) { next if $f =~ /^\.\.?$/; next unless -d "$curdir/$f"; print "pushing $curdir/$f\n"; push @dirs, "$curdir/$f"; } for (glob("$curdir/$filespec")) { print "processing $_\n"; } } $ perl 1004138.pl pushing ABC/DEF pushing ABC/GHI pushing ABC/JKL processing ABC/abcde.xml processing ABC/JKL/abc_x.xml processing ABC/JKL/abc_y.xml processing ABC/JKL/abc_z.xml pushing ABC/GHI/baz pushing ABC/GHI/foo pushing ABC/GHI/bar processing ABC/GHI/abc_5.xml processing ABC/GHI/abc_6.xml processing ABC/GHI/bar/abc_1.xml processing ABC/GHI/bar/abc_2.xml processing ABC/GHI/bar/abc_3.xml processing ABC/GHI/bar/abc_4.xml processing ABC/GHI/foo/abc_8.xml processing ABC/GHI/foo/abc_9.xml processing ABC/GHI/foo/abc_a.xml processing ABC/GHI/foo/abc_b.xml processing ABC/GHI/baz/abc_{7}.xml

    It's not particularly pretty, but it amused me for a few minutes. I didn't actually let it do file deletions because I'm loath to do automatic deletes until I've well tested such a script. It's a good thing, too. On my earlier attempt, a pair of bugs conspired to make the script "process" all "abc*.xml" files on my hard drive, rather than just those in the ABC directory.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      "I didn't actually let it do file deletions because I'm loath to do automatic deletes until I've well tested such a script."

      One nifty trick I sometimes use in situations like that is to make my script output text like this to STDOUT:

      rm ABC/JKL/abc_x.xml rm ABC/JKL/abc_y.xml rm ABC/JKL/abc_z.xml

      Then when I've played with it a few times, and I'm confident it's outputting the right commands, pipe the output into sh:

      perl myscript.pl | sh

      This is also good if you need to do a bunch of complex database changes. Just write SQL to STDOUT, and once you're sure it's OK, pipe it into your favourite command-line SQL tool.

      perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
Re: Recursive search and delete
by Arunbear (Parson) on Nov 16, 2012 at 11:59 UTC
    For this task you probably don't need to resort to Perl e.g. using the standard command line tools
    find -name 'abc*xml' | xargs rm
    would accomplish the same.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1004138]
Approved by shmem
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (5)
As of 2014-09-20 14:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (159 votes), past polls