views:

347

answers:

3

I have an IEnumerable<DirectoryInfo> that I want to filter down using an array of regular expressions to find the potential matches. I've been trying to join my directory and regex strings using linq, but can't seem to get it right. Here's what I'm trying to do...

string[] regexStrings = ... // some regex match code here.

// get all of the directories below some root that match my initial criteria.
var directories = from d in root.GetDirectories("*", SearchOption.AllDirectories)
                  where (d.Attributes & (FileAttributes.System | FileAttributes.Hidden)) == 0
                        && (d.GetDirectories().Where(dd => (dd.Attributes & (FileAttributes.System | FileAttributes.Hidden)) == 0).Count() > 0// has directories
                            || d.GetFiles().Where(ff => (ff.Attributes & (FileAttributes.Hidden | FileAttributes.System)) == 0).Count() > 0) // has files)
                  select d;

// filter the list of all directories based on the strings in the regex array
var filteredDirs = from d in directories
                   join s in regexStrings on Regex.IsMatch(d.FullName, s)  // compiler doesn't like this line
                   select d;

... any suggestions on how I can get this to work?

A: 

you are missing your Where keyword in front of the join

JohnathanKong
+1  A: 

I don't think that the approach you're taking is exactly what you want anyhow. That will check the name against ALL regex strings, rather than short circuiting on the first match. Additionally, it would duplicate the directories if one matched more than one pattern.

I think you want something like:

string[] regexStrings = ... // some regex match code here.

// get all of the directories below some root that match my initial criteria.
var directories = from d in root.GetDirectories("*", SearchOption.AllDirectories)
                  where (d.Attributes & (FileAttributes.System | FileAttributes.Hidden)) == 0
                        && (d.GetDirectories().Where(dd => (dd.Attributes & (FileAttributes.System | FileAttributes.Hidden)) == 0).Count() > 0// has directories
                            || d.GetFiles().Where(ff => (ff.Attributes & (FileAttributes.Hidden | FileAttributes.System)) == 0).Count() > 0) // has files)
                  select d;

// filter the list of all directories based on the strings in the regex array
var filteredDirs = directories.Where(d =>
    {
        foreach (string pattern in regexStrings)
        {
            if (System.Text.RegularExpressions.Regex.IsMatch(d.FullName, pattern))
            {
                return true;
            }
        }

        return false;
    });
Adam Robinson
+1 good answer.
Scott Ivey
+1  A: 

If you only want directories that match all regular expressions.

var result = directories
    .Where(d => regexStrings.All(s => Regex.IsMatch(d.FullName, s)));

If you only want directories that match at least one regular expressions.

var result = directories
    .Where(d => regexStrings.Any(s => Regex.IsMatch(d.FullName, s)));
Daniel Brückner
Ah, good call on the Any(). I keep forgetting about those!
Adam Robinson
Scott Ivey