tags:

views:

456

answers:

6

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

A: 
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.

+2  A: 

try

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

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

Alex Brown
you need to anchor that regex at the end of the string and escape the . somehow (I like to use a character class). As it is your regex will match "abcxh.txt". Try /[.]xh$/ instead.
Chas. Owens
Thanks - this worked!
Bi
Odd, I had lots of problems getting this answer to format correctly - I did escape the period, but it doesn't show (unless I escape the escape). Also the < and > were a struggle!Thanks for catching the $ anchor, I didn't test for that case.Fixed.
Alex Brown
@Alex Brown If you indent the code four spaces, SO will treat it as code rather than text. That means you can say <, \, etc. without it getting screwed with. You can also surround code with backticks for inline code examples. See this page for more information: http://stackoverflow.com/editing-help
Chas. Owens
+4  A: 

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
+2  A: 
opendir(MYDIR, $newpath) or die "$!";
my @files = grep{ !/\.xh$/ && /abc/ } readdir(MYDIR);
close MYDIR;
foreach (@files) { 
   do something
}
+1  A: 

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
Modify that second check to be /\.xh$/ and you'll be checking the right thing. :)
brian d foy
A: 

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 the map+splitpath.

ephemient
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
Huh? glob("./abc*") returns ("./abc.txt", "./abc.xh"); how else do you expect to twiddle that down to ("abc.txt")?
ephemient