0

I want to search a directory and its subdirectories for a single file.

The directory tree is very large and i don't want to search all the directory tree , but just search to the first found file.

Currently I have tried the following:

IEnumerable<string> files = Directory.EnumerateFiles(
Directory.GetCurrentDirectory(),
"myFile.ext",
SearchOption.AllDirectories);

myFileInfo = new FileInfo(files.First());

the problem with the code above is that it search all the directory tree.

my main focus in finding the file is performance.

fatihk
  • 7,789
  • 1
  • 26
  • 48
RayOldProf
  • 1,040
  • 4
  • 16
  • 40
  • 6
    You may have to write your own iterator of directories using DirectoryInfo and not search with the AllDirectories option to get the option you are looking for. – Martin Noreke Oct 27 '15 at 09:55
  • 1
    What's wrong with this: https://msdn.microsoft.com/en-us/library/ms143316.aspx ? – Nasreddine Oct 27 '15 at 09:58
  • Did you measure actual performance of EnumerateFiles before searching for better solution? – Andrey Oct 27 '15 at 10:05
  • 1
    What are you trying to do? Your code will *not* traverse all files - it *is* an enumerator which means you can get the first result before the entire tree gets traversed. Actually, if you used [DirectoryInfo.EnumerateFiles](https://msdn.microsoft.com/en-us/library/dd413343(v=vs.110).aspx) you'd get back a FileInfo directly, no need to get the path first, then create a FileInfo – Panagiotis Kanavos Oct 27 '15 at 10:06
  • This is the fastest method you could find, see [here](http://stackoverflow.com/a/5669635/1155650) for difference. – Rohit Vipin Mathews Oct 27 '15 at 10:11

3 Answers3

1

What you have tried is indeed the solution. It does not loop through all your directory tree but a part of it; until the file is found.

Alternatively - as commented -, you can get FileInfo class directly (if necessary):

FileInfo fileInfo = new DirectoryInfo(Directory.GetCurrentDirectory())
                            .EnumerateFiles("myFile.ext", SearchOption.AllDirectories)
                            .FirstOrDefault();
Alb
  • 412
  • 5
  • 12
0
String searchFile(String searchPath, String fileName)
{
    DirectoryInfo dir = new DirectoryInfo(searchPath);
    DirectoryInfo[] dirs = dir.GetDirectories();

    FileInfo[] files = dir.GetFiles();
    foreach (FileInfo file in files)
    {
        if (file.Name.Equals(fileName))
            return searchPath;
    }

    foreach (DirectoryInfo subDir in dirs)
    {
        String value = searchFile(Path.Combine(searchPath, subDir.Name), fileName);
        if (value != null)
            return value;
    }
    return null;
}

private void Form1_Load(object sender, EventArgs e)
{
    String searchPath = @"C:\PathHere";
    String searchFile = "log.txt";

    String foundFileAt = this.searchFile(searchPath, searchFile);
}
AsfK
  • 3,328
  • 4
  • 36
  • 73
0

How about this:

public string FindFirstFile(string dir, string file)
{
    if (System.IO.File.Exists(Path.Combine(dir, file)))
    {
        return Path.Combine(dir, file);
    }
    foreach (var subDir in System.IO.Directory.EnumerateDirectories(dir))
    {
        var result = FindFirstFile(subDir, file);
        if (result != null)
        {
            return result;
        }
    }
    return null;
}

Usage:

var topDirectory = @"D:\top directory";
var file = "foo.txt";
var theFile = FindFirstFile(topDirectory, file);

It's more complex than the build in functionality, but you get more control over when when you return.

Kvam
  • 2,148
  • 1
  • 20
  • 32