Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ignore exceptions of Directory.EnumerateFiles, skip those files

Tags:

c#

While enumerating I would like to Skip/Ignore exception.

I try to add a try catch in the selector:

static IEnumerable<string> GetSafeAllFiles
    (string path, string searchPattern, SearchOption searchOption = SearchOption.AllDirectories)
{
    return Directory.EnumerateFiles(path, searchPattern, searchOption)
                    .Select(f =>
                    {
                        try
                        {
                            return f;
                        }
                        catch (Exception e)
                        {
                            return string.Empty;
                        }
                    });
}

I try using a solution from an accepted answer:

var test23 = Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories)
                      .SkipExceptions().Take(100);

With no result, as it will stop after the first error. So I try to implement my own :

static IEnumerable<string> test12(string path, string searchPattern, SearchOption searchOption = SearchOption.AllDirectories)
{
    if (string.IsNullOrEmpty(path))
    {
        throw new ArgumentNullException("path");
    }
    if (string.IsNullOrEmpty(searchPattern))
    {
        throw new ArgumentNullException("searchPattern");
    }

    Queue<string> stillToProcess = new Queue<string>(new[] { path });

    foreach (var dir in Directory.EnumerateDirectories(path))
    {
        stillToProcess.Enqueue(dir);
    }

    while (stillToProcess.Count > 0)
    {
        string currentPath = stillToProcess.Dequeue();
        IEnumerable<string> ret = Enumerable.Empty<string>();
        try
        {
            ret = Directory.EnumerateFiles(currentPath, searchPattern);
        }
        catch (UnauthorizedAccessException e)
        { }
                    // yield! keyword
        foreach (var i in ret) { yield return i; }
    }
    yield break;
}

But it skip directory if there is one error. When I want to skip only the error file.

In order to test, possible solution please do it on c:\$Recycle.Bin, as it's the easiest source of UnauthorizedAccessException.

like image 619
xdtTransform Avatar asked Nov 16 '22 23:11

xdtTransform


1 Answers

This is what i came up with:

public static IEnumerable<FileInfo> EnumerateFilesIgnoreErrors(IEnumerable<FileInfo> files)
{
    using (var e1 = files.GetEnumerator())
    {
        while (true)
        {
            FileInfo cur = null;

            try
            {
                // MoveNext() can throw an Exception
                if (! e1.MoveNext())
                    break;

                cur = e1.Current;

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
            }

            if (cur != null)
            {
                yield return cur;
            }
        }
    }
}

Use like this:

var myFiles = new DirectoryInfo(@"C:\")
           .EnumerateFiles("*", SearchOption.AllDirectories);
           
foreach (FileInfo fi in EnumerateFilesIgnoreErrors(myFiles))
{
    Debug.WriteLine(fi.Name);
} 

You can also use it like this:

var myList = EnumerateFilesIgnoreErrors(myFiles).ToList();

Works on "c:\$Recycle.Bin" etc
Ignores UnauthorizedAccessException

like image 109
Charles Avatar answered Jan 25 '23 14:01

Charles