2

I am creating an application which finds duplication in files. When I search files like:

try
{
    string[] allFiles = Directory.GetFiles(
        directoryPath, "*.*", SearchOption.AllDirectories
    );

    for (int i = 0; i < allFiles.Length; i++)
    {
      //decisions
    }
}

catch (UnauthorizedAccessException ex)
{
    MessageBox.Show(ex.Message);
}

it says

Access to path 'C:\$Recycle.Bin....... ' is denied.

I want if a folder is not accessible then move to the next but execution of program stops at Directory.GetFiles method.

Yuck
  • 49,664
  • 13
  • 105
  • 135
Muhammad Ali Dildar
  • 1,467
  • 6
  • 24
  • 35
  • Let's call it a feature and not a bug. No sane user is going to put up with a program that goes zombie for *minutes* while it enumerates every file on the c:\ drive. A terabyte is a big number. – Hans Passant Dec 17 '11 at 22:05
  • @Hans who says the app is running a UI when the code executes? – sq33G Dec 17 '11 at 22:22

1 Answers1

4

Here's a class that will work:

public static class FileDirectorySearcher
{
    public static IEnumerable<string> Search(string searchPath, string searchPattern)
    {
        IEnumerable<string> files = GetFileSystemEntries(searchPath, searchPattern);

        foreach (string file in files)
        {
            yield return file;
        }

        IEnumerable<string> directories = GetDirectories(searchPath);

        foreach (string directory in directories)
        {
            files = Search(directory, searchPattern);

            foreach (string file in files)
            {
                yield return file;
            }
        }
    }

    private static IEnumerable<string> GetDirectories(string directory)
    {
        IEnumerable<string> subDirectories = null;
        try
        {
            subDirectories = Directory.EnumerateDirectories(directory, "*.*", SearchOption.TopDirectoryOnly);
        }
        catch (UnauthorizedAccessException)
        {
        }

        if (subDirectories != null)
        {
            foreach (string subDirectory in subDirectories)
            {
                yield return subDirectory;
            }
        }
    }

    private static IEnumerable<string> GetFileSystemEntries(string directory, string searchPattern)
    {
        IEnumerable<string> files = null;
        try
        {
            files = Directory.EnumerateFileSystemEntries(directory, searchPattern, SearchOption.TopDirectoryOnly);
        }
        catch (UnauthorizedAccessException)
        {
        }

        if (files != null)
        {
            foreach (string file in files)
            {
                yield return file;
            }
        }
    }
}

You can the use it like this:

IEnumerable<string> filesOrDirectories = FileDirectorySearcher.Search(@"C:\", "*.txt");

foreach (string fileOrDirectory in filesOrDirectories)
{
   // Do something here.
}

It's recursive, but the use of yield gives it a low memory footprint (under 10KB in my testing). If you want only files that match the pattern and not directories as well just replace EnumerateFileSystemEntries with EnumerateFiles.

JamieSee
  • 12,696
  • 2
  • 31
  • 47
  • That code has a major bug... because EnumerateDirectories will return an IEnumerable and then when you iterate over the IEnumerable you will get the UnauthorizedAccessException.. I've updated your code above. – Blake Niemyjski Jun 12 '12 at 16:53
  • Hi @BlakeNiemyjski, I've been looking at the code but have been unable to reproduce the problem that you said your edit addresses. Can you tell me the specifc steps to reproduce it? – JamieSee Jun 12 '12 at 22:45
  • Your code was picking up System Folders like the recycle bin. I'd run your code as an administrator and point it to your windows drive – Blake Niemyjski Jul 16 '12 at 18:26
  • @BlakeNiemyjski I tried it on a Windows 2008 R2 server as Admin, on an XP workstation as standard user, and on an XP workstation as Admin with `FileDirectorySearcher.Search(@"C:\", "*.*");`. I still couldn't reproduce an **uncaught** UnauthorizedAccessException. As an admin it enumerated the RECYCLER folder's contents and as a standard user it caught the exception and kept right on going. – JamieSee Jul 31 '12 at 21:08
  • I was seeing this issue on Windows 7 x64. I pointed it to both my C drive and my other hard drives. Try enabling show system and hidden folders in Explorer.. – Blake Niemyjski Aug 08 '12 at 17:35
  • Works, but I also had to catch `DirectoryNotFoundException` when enumerating the WSL filesystem from Windows, found when testing this on my home directory. – stijn Apr 16 '21 at 07:40
  • Actually, also PathTooLongException: https://learn.microsoft.com/en-us/dotnet/api/system.io.directoryinfo.enumeratedirectories?view=net-5.0 – stijn Apr 16 '21 at 07:59