How to use $ File :: Find :: prune?

I need to edit the cue files in the first directory and not go recursively into 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 tried the options

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

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

thanks

+4
source share
4 answers

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

 for (glob("*.cue")) { read_cue($_); } 
+7
source

If you want to filter out subdirectories recursive in File :: Find, you should use the preprocess function (and not the $ File :: Find :: prune variable), as this gives you much more control. The idea is to provide a function that is called once for a directory and a list of files and subdirectories is passed; the return value is a filtered list to go to the desired function and (for subdirectories) for recursion.

As msw and Brian commented, your example will probably be better served by glob, but if you want to use File :: Find, you can do something like the following. Here, the preprocess function calls -f for each file or directory that it specified, returning a list of files. Then the requested function is called only for these files, and File :: Find does not recurs in 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 complex file crawlers. For example, I wanted to find all the files in the Java project directory without returning to subdirectories starting with β€œ.”, Such as β€œ.idea” and β€œ.svn” created by IntelliJ and Subversion. You can do this by changing 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 /^[^.]/) } @_; } 
+4
source

If you only need files in a directory without searching for subdirectories, you do not want to use File :: Find. A simple glob probably does the trick:

 my @files = glob( "$dir_source/*.cue" ); 

You do not need this routine. In general, when you do a lot of work for a task that you think should be simple, you are probably mistaken. :)

+1
source

Say you have a directory subtree with

  /tmp/foo/file.cue
 /tmp/foo/bar/file.cue
 /tmp/foo/bar/baz/file.cue 

Launch

 #! /usr/bin/perl use warnings; use strict; use File::Find; sub read_cue { if (-f && /\.cue$/) { print "found $File::Find::name\n"; } } @ARGV = (".") unless @ARGV; find \&read_cue => @ARGV; 

exits

  found /tmp/foo/file.cue
 found /tmp/foo/bar/file.cue
 found /tmp/foo/bar/baz/file.cue 

But if you remember the directories in which you found the cue files

 #! /usr/bin/perl use warnings; use strict; use File::Find; my %seen_cue; sub read_cue { if (-f && /\.cue$/) { print "found $File::Find::name\n"; ++$seen_cue{$File::Find::dir}; } elsif (-d && $seen_cue{$File::Find::dir}) { $File::Find::prune = 1; } } @ARGV = (".") unless @ARGV; find \&read_cue => @ARGV; 

you get only a file with keywords:

  found /tmp/foo/file.cue 

What, since $File::Find::prune emulates the -prune find parameter, which affects directory processing:

-prune

True if the file is a directory, do not enter it.

-1
source

All Articles