10

I need to search for files in a directory that begin with a particular pattern, say "abc". I also need to eliminate all the files in the result that end with ".xh". I am not sure how to go about doing it in Perl.

I have something like this:

opendir(MYDIR, $newpath);
my @files = grep(/abc\*.*/,readdir(MYDIR)); # DOES NOT WORK

I also need to eliminate all files from result that end with ".xh"

Thanks, Bi

Ether
  • 53,118
  • 13
  • 86
  • 159
Bi.
  • 1,846
  • 8
  • 25
  • 34

6 Answers6

7

try

@files = grep {!/\.xh$/} <$MYDIR/abc*>;

where MYDIR is a string containing the path of your directory.

Chas. Owens
  • 64,182
  • 22
  • 135
  • 226
Alex Brown
  • 41,819
  • 10
  • 94
  • 108
7

opendir(MYDIR, $newpath); my @files = grep(/abc*.*/,readdir(MYDIR)); #DOES NOT WORK

You are confusing a regex pattern with a glob pattern.

#!/usr/bin/perl

use strict;
use warnings;

opendir my $dir_h, '.'
    or die "Cannot open directory: $!";

my @files = grep { /abc/ and not /\.xh$/ } readdir $dir_h;

closedir $dir_h;

print "$_\n" for @files;
Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
3
opendir(MYDIR, $newpath) or die "$!";
my @files = grep{ !/\.xh$/ && /abc/ } readdir(MYDIR);
close MYDIR;
foreach (@files) { 
   do something
}
user118435
  • 173
  • 4
2

The point that kevinadc and Sinan Unur are using but not mentioning is that readdir() returns a list of all the entries in the directory when called in list context. You can then use any list operator on that. That's why you can use:

my @files = grep (/abc/ && !/\.xh$/), readdir MYDIR;

So:

readdir MYDIR

returns a list of all the files in MYDIR.

And:

grep (/abc/ && !/\.xh$/)

returns all the elements returned by readdir MYDIR that match the criteria there.

Nathan Fellman
  • 122,701
  • 101
  • 260
  • 319
-1
foreach $file (@files)
{
    my $fileN = $1 if $file =~ /([^\/]+)$/;

    if ($fileN =~ /\.xh$/)
    {
          unlink $file;
          next;
    }
    if ($fileN =~ /^abc/)
    {
          open(FILE, "<$file");
          while(<FILE>)
          {
             # read through file.
          }
    }
 }

also, all files in a directory can be accessed by doing:

$DIR = "/somedir/somepath";
foreach $file (<$DIR/*>)
{
  # apply file checks here like above.
}

ALternatively you can use the perl module File::find.

user105033
  • 18,800
  • 19
  • 58
  • 69
-1

Instead of using opendir and filtering readdir (don't forget to closedir!), you could instead use glob:

use File::Spec::Functions qw(catfile splitpath);

my @files =
    grep !/^\.xh$/,                # filter out names ending in ".xh"
    map +(splitpath $_)[-1],       # filename only
    glob                           # perform shell-like glob expansion
        catfile $newpath, 'abc*';  # "$newpath/abc*" (or \ or :, depending on OS)

If you don't care about eliminating the $newpath prefixed to the results of glob, get rid of the map+splitpath.

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
ephemient
  • 198,619
  • 38
  • 280
  • 391
  • There's no need for the map or the splitpath. Either it ends in .xh or it doesn't. The extra work doesn't change that. – brian d foy Jun 12 '09 at 21:14
  • Huh? glob("./abc*") returns ("./abc.txt", "./abc.xh"); how else do you expect to twiddle that down to ("abc.txt")? – ephemient Jun 12 '09 at 21:35