Filter filenames by pattern
Asked Answered
S

6

11

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

Supernova answered 11/6, 2009 at 21:0 Comment(0)
C
8

try

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

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

Capitulum answered 11/6, 2009 at 21:18 Comment(0)
K
8

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;
Kagera answered 11/6, 2009 at 21:20 Comment(0)
P
3
opendir(MYDIR, $newpath) or die "$!";
my @files = grep{ !/\.xh$/ && /abc/ } readdir(MYDIR);
close MYDIR;
foreach (@files) { 
   do something
}
Precessional answered 11/6, 2009 at 21:31 Comment(0)
S
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.

Sitting answered 11/6, 2009 at 21:40 Comment(1)
Modify that second check to be /\.xh$/ and you'll be checking the right thing. :)Clearcole
A
-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.

Anteater answered 11/6, 2009 at 21:7 Comment(0)
L
-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.

Larondalarosa answered 12/6, 2009 at 17:45 Comment(2)
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.Clearcole
Huh? glob("./abc*") returns ("./abc.txt", "./abc.xh"); how else do you expect to twiddle that down to ("abc.txt")?Larondalarosa

© 2022 - 2024 — McMap. All rights reserved.