-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFileSystemEnumerable.cs
135 lines (116 loc) · 4.87 KB
/
FileSystemEnumerable.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
// This code is public domain - from the StackOverflow post at
// <https://stackoverflow.com/questions/13130052/directoryinfo-enumeratefiles-causes-unauthorizedaccessexception-and-other>
// Provided by Matthew Brubaker. I do not own this code in any way; I am merely putting this here to facilitate
// access by the public/improvements.
// CHANGELOG
//
// 26 Jan 2019 (Brian Hart): Added two overloads of a static Search() method so that you do not have to call
// the constructor directly. Helpful for cleaner syntax in loops.
// 29 Jan 2019 (Brian Hart) Did a CodeMaid code cleanup on the file (formatted and sorted usings) and commented out
// all the calls to ILog, to remove the dependency on log4net, which might not be something that everyone who wants to
// utilize this class might also utilize.
//
/// <summary>
/// Enumerates the files and folders in the specified directory, yielding results as they come, and
/// skipping files and folders to which the operating system denies us access.
/// </summary>
/// <remarks>
/// The functionality in this class is known to work, so it has been marked with the [ExcludeFromCodeCoverage]
/// attribute.
/// </remarks>
[ExcludeFromCodeCoverage]
public class FileSystemEnumerable : IEnumerable<FileSystemInfo>
{
//private ILog _logger = LogManager.GetLogger(typeof(FileSystemEnumerable));
private readonly DirectoryInfo _root;
private readonly IList<string> _patterns;
private readonly SearchOption _option;
public static IEnumerable<FileSystemInfo> Search(DirectoryInfo root, string pattern = "*",
SearchOption option = SearchOption.AllDirectories)
{
if (!root.Exists)
throw new DirectoryNotFoundException($"The folder '{root.FullName}' could not be located.");
/* If the search pattern string is blank, then default to the wildcard (*) pattern. */
if (string.IsNullOrWhiteSpace(pattern))
pattern = "*";
return new FileSystemEnumerable(root, pattern, option);
}
public static IEnumerable<FileSystemInfo> Search(string root, string pattern = "*",
SearchOption option = SearchOption.AllDirectories)
{
if (!Directory.Exists(root))
throw new DirectoryNotFoundException($"The folder '{root}' could not be located.");
/* If the search pattern string is blank, then default to the wildcard (*) pattern. */
if (string.IsNullOrWhiteSpace(pattern))
pattern = "*";
var rootDirectoryInfo = new DirectoryInfo(root);
return new FileSystemEnumerable(rootDirectoryInfo, pattern, option);
}
public FileSystemEnumerable(DirectoryInfo root, string pattern, SearchOption option)
{
_root = root;
_patterns = new List<string> { pattern };
_option = option;
}
public FileSystemEnumerable(DirectoryInfo root, IList<string> patterns, SearchOption option)
{
_root = root;
_patterns = patterns;
_option = option;
}
public IEnumerator<FileSystemInfo> GetEnumerator()
{
if (_root == null || !_root.Exists) yield break;
IEnumerable<FileSystemInfo> matches = new List<FileSystemInfo>();
try
{
//_logger.DebugFormat("Attempting to enumerate '{0}'", _root.FullName);
matches = _patterns.Aggregate(matches, (current, pattern) => current.Concat(_root.EnumerateDirectories(pattern, SearchOption.TopDirectoryOnly))
.Concat(_root.EnumerateFiles(pattern, SearchOption.TopDirectoryOnly)));
}
catch (UnauthorizedAccessException)
{
//_logger.WarnFormat("Unable to access '{0}'. Skipping...", _root.FullName);
yield break;
}
catch (PathTooLongException)
{
//_logger.Warn(string.Format(@"Could not process path '{0}\{1}'.", _root.Parent.FullName, _root.Name), ptle);
yield break;
}
catch (System.IO.IOException)
{
// "The symbolic link cannot be followed because its type is disabled."
// "The specified network name is no longer available."
//_logger.Warn(string.Format(@"Could not process path (check SymlinkEvaluation rules)'{0}\{1}'.", _root.Parent.FullName, _root.Name), e);
yield break;
}
//_logger.DebugFormat("Returning all objects that match the pattern(s) '{0}'", string.Join(",", _patterns));
foreach (var file in matches)
{
yield return file;
}
if (_option != SearchOption.AllDirectories)
yield break;
//_logger.DebugFormat("Enumerating all child directories.");
foreach (var dir in _root.EnumerateDirectories("*", SearchOption.TopDirectoryOnly))
{
//_logger.DebugFormat("Enumerating '{0}'", dir.FullName);
var fileSystemInfos = new FileSystemEnumerable(dir, _patterns, _option);
foreach (var match in fileSystemInfos)
{
yield return match;
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}