Wednesday, September 17, 2014

Perl : Find files using File::Find



How to find the list of files in Perl  like the UNIX find command? The answer is File::Find CPAN module. Let us see in this article how to use the File::Find module.

File::Find:
   File::Find module contains 2 modules: find and finddepth. Both are used to find the files, the difference being the order in which the files and directories are parsed. find has all the options like the Unix find command.

1. Find all .txt files:
use File::Find;

my @files;
my @dirpath=qw(/home/user1/);
find(sub {
           push @files,$File::Find::name if (-f $File::Find::name and /\.txt$/);
      }, @dirpath);

print join "\n",@files;
find function takes 2 arguments:
1. The first argument is a subroutine which is called for each and every file found by the find function.
2. The 2nd argument is list of directories where the find function will search for files.

By default, the find function searches for all files and directories which in Unix find command can be written as:
find .
 Every file found by the find command is pushed into the array @files if it is a file (-f) and has .txt extension(\.txt$). The variable $File::Find::name contains the complete path name of the file.

2. Find all .txt or .xml files:
my @files;
my @dirpath=qw(/home/user1/);
find(sub {
      push @files,$File::Find::name if (-f $File::Find::name and /\.(txt|xml)$/);
    }, @dirpath);

print join "\n",@files;
 The regex used here checks for either a txt file or a xml file.
The Unix equivalent of this is:
$ find /home/user1 \( -name "*.txt" -o -name "*.xml" \)
3Find all dirs:
use File::Find;

my @files;
my @dirpath=qw(/home/user1);
find(sub {
        push @files,$File::Find::name if (-d $File::Find::name );
      }, @dirpath);

print join "\n",@files;
  The directories alone are filtered by checking for the -d option against the $File::Find::name variable.
The Unix equivalent of this is:
$ find /home/user1 -type d
4. Files modified in the last 1 day:
use File::Find;

my @files;
my @dirpath=qw(/home/user1/);
find(sub {
      push @files,$File::Find::name if (-f $File::Find::name and int(-M $_) < 1);
    }, @dirpath);

print join "\n",@files;
-M filename gives the age of the file which is nothing but the number of days since it is last modified. By checking this value to be less than 1, files modified in the last day can be retrieved.

The Unix equivalent of this is:
$ find /home/user1 -mtime -1
5. Files modified in the last 1 hour:
my @files;
my @dirpath=qw(/home/user1/);
find(sub {
      push @files,$File::Find::name if (-f $File::Find::name and (-M $_) < 1/24);
    }, @dirpath);

print join "\n",@files;
Since -M gives the number of days since the file is last modified, by checking it against 1/24 filters only those files whose age is less than 1 hour.

The Unix equivalent of this is:
$ find /home/user1 -mmin -60
6. Files modified in the last 30 mins:
my @files;
my @dirpath=qw(/home/user1/);
find(sub {
    push @files,$File::Find::name if (-f $File::Find::name and (-M $_) < 0.5/24);   }, @dirpath);

print join "\n",@files;
The Unix equivalent of this is:
$ find /home/user1 -mmin -30
This module, along with the functions, provides some variables as well. The following are those:
$name : the full name of the file
$dir : contains the name of the current directory in which find is finding.

Note: The find2perl command internally uses the File::Find module itself.

No comments:

Post a Comment