30 March 2010

Using LINQ to get filenames from a directory structure using multiple include and exclude patterns

This example shows how to get list of file names from a directory (including subdirectories) using multiple include- and exclude patterns.

The buildin method System.IO.Directory.GetFiles can handle only one include pattern and no exclude pattern and multiple patterns a definitely out of the question.

So I had to write a little helper method using LINQ to do the trick!

/// <summary>
/// Get the files from the specified path, including subdirectories, which match the specified pattern.
/// Note: To specified multiple patterns, separate them by a semicolumn (;)
/// </summary>
/// <param name="path">The path.</param>
/// <param name="includePatterns">An array of include patterns. Using wildcards.</param>
/// <param name="excludePatterns">An array of exclude patterns. Using Regular expressions.</param>
/// <returns>Returns an array of filenames.</returns>
public static string[] GetFiles(string path, string[] includePatterns, string[] excludePatterns)
{
 if (string.IsNullOrEmpty(path))
 {
  throw new ArgumentNullException("path", "Argument should not be NULL or an empty string.");
 }
 if (includePatterns == null)
 {
  includePatterns = new string[0];
 }
 if (excludePatterns == null)
 {
  excludePatterns = new string[0];
 }

 var files = from includePattern in includePatterns
    from includeFile in Directory.GetFiles(path, includePattern, SearchOption.AllDirectories)
    from excludePattern in excludePatterns.DefaultIfEmpty()
    where excludePattern == null || !Regex.IsMatch(includeFile, excludePattern, RegexOptions.IgnoreCase)
    select includeFile;

 return files.ToArray();
}

The following example gets all files that match the wildcard patterns 'DdH.*.Helpers.dll' & 'DdH.*.exe' from the c:\temp directory, but will exclude all files that match the regular expression 'Tests\.dll'.

string[] fileNames = GetFiles(@"c:\temp", new string[] { "DdH.Helpers.*.dll", "DdH.*.exe" }, new string[] { "Tests\.dll" });