Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use $File::Find::prune?

Tags:

perl

I have a need to edit cue files in the first directory and not go recursively in the subdirectories.

find(\&read_cue, $dir_source);
sub read_cue {
    /\.cue$/ or return;

    my $fd = $File::Find::dir;
    my $fn = $File::Find::name; 
    tie my @lines, 'Tie::File', $fn
      or die "could not tie file: $!";

    foreach (@lines) {
        s/some substitution//;
    }

    untie @lines;
}

I've tried variations of

$File::Find::prune = 1;
return;  

but with no success. Where should I place and define $File::Find::prune?

Thanks

like image 683
thebourneid Avatar asked Dec 17 '22 22:12

thebourneid


2 Answers

If you don't want to recurse, you probably want to use glob:

for  (glob("*.cue")) {
   read_cue($_);
}
like image 80
msw Avatar answered Jan 05 '23 14:01

msw


If you want to filter the subdirectories recursed into by File::Find, you should use the preprocess function (not the $File::Find::prune variable) as this gives you much more control. The idea is to provide a function which is called once per directory, and is passed a list of files and subdirectories; the return value is the filtered list to pass to the wanted function, and (for subdirectories) to recurse into.

As msw and Brian have commented, your example would probably be better served by a glob, but if you wanted to use File::Find, you might do something like the following. Here, the preprocess function calls -f on every file or directory it's given, returning a list of files. Then the wanted function is called only for those files, and File::Find does not recurse into any of the subdirectories:

use strict;
use File::Find;

# Function is called once per directory, with a list of files and
# subdirectories; the return value is the filtered list to pass to
# the wanted function.
sub preprocess { return grep { -f } @_; }

# Function is called once per file or subdirectory.
sub wanted { print "$File::Find::name\n" if /\.cue$/; }

# Find files in or below the current directory.
find { preprocess => \&preprocess, wanted => \&wanted }, '.';

This can be used to create much more sophisticated file finders. For example, I wanted to find all files in a Java project directory, without recursing into subdirectories starting with ".", such as ".idea" and ".svn", created by IntelliJ and Subversion. You can do this by modifying the preprocess function:

# Function is called once per directory, with a list of files and
# subdirectories; return value is the filtered list to pass to the
# wanted function.
sub preprocess { return grep { -f or (-d and /^[^.]/) } @_; }
like image 44
Huw Walters Avatar answered Jan 05 '23 13:01

Huw Walters