0

In perl I can loop through the files in the current directory by doing the following:

foreach $file (<*.*>) {
        print "$file found\n";
        # do stuff
}

How can I do the same thing but to all files in all sub-directories?

CJ7
  • 22,579
  • 65
  • 193
  • 321
  • If you don't want to use additional modules, may be my [answer](http://stackoverflow.com/questions/36407997/rename-files-of-a-folder-and-its-folders-children/36425685#36425685) will help you – red0ct Apr 11 '16 at 07:34

2 Answers2

6

File::Find::Rule is a great module for recursively listing files.

All files (as you asked):

use File::Find::Rule qw( );

for my $qfn (File::Find::Rule->in(".")) {
   ...
}

Just the files with "." in their name (as per your example):

use File::Find::Rule qw( );

for my $qfn (File::Find::Rule->name("*.*")->in(".")) {
   ...
}

Adding ->file limits the results to plain files (filtering out directories).

ikegami
  • 367,544
  • 15
  • 269
  • 518
0

I find File::Find::Rule unnecessarily fussy and clumsy, especially for a simple application like this. Ultimately it is just a wrapper for the core module File::Find, and I think the base class itself is a good choice for a straightforward application like yours

File::Find allows you to specify a callback subroutine that will be executed for every node (file or directory) within a specified root directory

By default, that subroutine is called with the following context

  • $File::Find::name is set to the full path to the node
  • $File::Find::dir is set to the path to the directory containing the
  • $_ is set to the name of the node, without its path
  • The current working directory is set to $File::Find::dir

If you want, say, to list all files beneath your current directory, then you would write this. All nodes but plain files are rejected using the -f file test operator, works on $_ and finds the right file because the working directory has been temporarily changed

use strict;
use warnings 'all';

use File::Find 'find';

find(\&wanted, '.');

sub wanted {

    return unless -f;

    print $File::Find::name, "\n";
}

If you prefer, you can use an anonymous subroutine within the call to find. This code does exactly the same thing

find(sub {
    return unless -f;
    print $File::Find::name, "\n";
}, '.');
Borodin
  • 126,100
  • 9
  • 70
  • 144
  • I prefer the use of `File::Find::Rule`. You haven't properly explained your objection to it. – CJ7 Apr 11 '16 at 23:19