2

Using C# (.NET), how can I search a file system given a directory search mask like this: (?)

\\server\Scanner\images\*Images\*\*_*

For example, I need to first find all top-level directories:

\\server\Scanner\images\Job1Images
\\server\Scanner\images\Job2Images

...then I need to procede further with the search mask:

\\server\Scanner\images\Job1Images\*\*_*
\\server\Scanner\images\Job2Images\*\*_*

This doesn't seem too complicated but I can't figure it out for the life of me...

As mentioned above, I'm using C# and .NET. The search can be trying to locate directories or files. (i.e. *.txt, or <*Directory>)

SofaKng
  • 1,063
  • 1
  • 11
  • 32
  • So I am not clear on what your wild cards are - are you looking for a specific file or directory with an underscore in the name (based on your example)? – tsells Nov 20 '12 at 16:57
  • Sorry... I'm looking for something that fits the entire mask. For example, "\\server\Scanner\images\Job1Images\file.txt" wouldn't work but it doesn't fit the entire mask. Only something like "\\server\Scanner\images\Job1Images\Folder2\MyFile_File.txt" would work. Does that make sense? – SofaKng Nov 20 '12 at 17:25
  • I am not getting the recursive part. Would you want to match \\server\Scanner\images\recursive\Job1Images\*\*_*? – paparazzo Nov 20 '12 at 19:43
  • You only want the files found in subfolders of the Job*Images folders? You do not want the files in the Job*Images folders as well? – Panos Rontogiannis Nov 20 '12 at 20:29
  • Unless I misunderstood what you were looking for doesn't my answer give you exactly what you want? If not, why not? What you are looking for isn't exactly clear – Mario Nov 21 '12 at 18:40

4 Answers4

2

Like this:

Top Level Directories:

  //get Top level
   string[] TopLevel = Directory.GetDirectories(path);

And then you will have to do a resursive function of this folders using wildcard pattern, for example:

 // Only get subdirectories that begin with the letter "p." 
            string pattern = "p*";
            string[] dirs = folder.GetDirectories(path, pattern);

I suggest you play with wildcards to get the array output and you will figure out which is the best way, if using resursive function or directly quering paths.

Carlos Landeras
  • 11,025
  • 11
  • 56
  • 82
1

Edit: Ahh, new functionality with .NET 4 so you don't have to do a recursive function (Thanks Matthew Brubaker)

IEnumerable<String> matchingFilePaths2 = System.IO.Directory.EnumerateFiles(@"C:\some folder to start in", filePatternToMatchOn, System.IO.SearchOption.AllDirectories);




First Answer:

//get all files that have an underscore - searches all folders under the start folder
List<String> matchingFilePaths = new List<string>();
String filePatternToMatchOn = "*_*";
FileUtilities.GetAllFilesMatchingPattern(@"C:\some folder to start in", ref matchingFilePaths, filePatternToMatchOn);

...

public static void GetAllFilesMatchingPattern(String pathToGetFilesIn, ref List<String> fullFilePaths, String searchPattern)
{
    //get all files in current directory that match the pattern
    String[] filePathsInCurrentDir = Directory.GetFiles(pathToGetFilesIn, searchPattern);
    foreach (String fullPath in filePathsInCurrentDir)
    {
        fullFilePaths.Add(fullPath);
    }

    //call this method recursively for all directories
    String[] directories = Directory.GetDirectories(pathToGetFilesIn);
    foreach (String path in directories)
    {
        GetAllFilesMatchingPattern(path, ref fullFilePaths, searchPattern);
    }
}
Mario
  • 3,405
  • 6
  • 38
  • 48
1
    public static IEnumerable<string> GetImages()
{    
    //For each "*Image" directory
    foreach (var jobFolder in Directory.EnumerateDirectories(@"\\server\Scanner\images", "*Images"))
    {
        //For each first level subdirectory
        foreach (var jobSubFolder in Directory.EnumerateDirectories(jobFolder))
        {
            //Enumerate each file containing a '_'
            foreach (var filePath in Directory.EnumerateFiles(jobSubFolder, "*_*", SearchOption.TopDirectoryOnly))
            {                               
                yield return filePath;
            }
        }
    }
}

Only the files from the first level subdirectories of each "*Image" directory are enumerated.

Finally you can use it with:

foreach (var path in GetImages())
            {
                Console.WriteLine(path);
            }
Panos Rontogiannis
  • 4,154
  • 1
  • 24
  • 29
  • 1
    Please, encourage the use of http://msdn.microsoft.com/en-us/library/system.io.directory.enumeratefiles.aspx as it is far more efficient and does not populate the list until it is necessary. – Matthew Brubaker Nov 20 '12 at 19:12
  • @MatthewBrubaker You are right! Thanks. Will update my answer. – Panos Rontogiannis Nov 20 '12 at 19:49
  • This looks great, but won't this first obtain a list of every file in the file system and then perform a regex match against it? I would think it would be awfully slow if there are "top-level" directories that don't match the regex but because this is matching against every file in the system. (see my OP example of what I'm talking about when filtering the directories as I go deeper, etc.) – SofaKng Nov 20 '12 at 20:03
  • @SofaKng It will try to match the regex on any file found under your "images" folder. If you expect a specific image format you could replace *.* with let's say *.jpg and enumerate only the JPG images. – Panos Rontogiannis Nov 20 '12 at 20:24
0

There is a C# procedure where you can search folder by path pattern with wildcards like * and ?.

Example if path pattern C:\Folder?*\Folder2 is passed to the procedru, then a list of folder path will be returned

C:\Folder1\A\Folder2

C:\FolderA\B\Folder2

...

and so on

static List<string> GetFoldersByPathPattern(string folderPathPattern)
{
    List<string> directories = new List<string>();
    directories.Add("");

    string[] folderParts = folderPathPattern.Split(new char[] { '\\' }, StringSplitOptions.None);
    foreach (string folderPart in folderParts)
    {

        if (folderPart.Contains('*') || folderPart.Contains('?'))
        {
            List<string> newDirectories = new List<string>();

            foreach (string directory in directories)
            {
                foreach (string newDirectory in Directory.GetDirectories(directory, folderPart))
                {
                    newDirectories.Add(newDirectory);
                }
            }

            directories = newDirectories;
        }
        else
        {
            for (int i = 0; i < directories.Count(); i++)
            {
                directories[i] = directories[i] + folderPart + "\\";
            }
        }
    }

    return directories;
}