public static IEnumerable <FileSystemInfo> Traverse(this DirectoryInfo root, string pattern, bool caseSensitive, bool emitFiles, bool emitDirectories) { var parser = new Parser(pattern); var segments = parser.ParseTree().Segments; var cache = new TraverseOptions(caseSensitive, emitFiles, emitDirectories); return(segments.Length == 0 ? new FileSystemInfo[0] : Traverse(root, segments, cache)); }
internal static IEnumerable <FileSystemInfo> Traverse(DirectoryInfo root, Segment[] segments, int segmentIndex, TraverseOptions options) { if (segmentIndex == segments.Length) { return(options.EmitDirectories ? Enumerable.Repeat <FileSystemInfo>(root, 1) : emptyFileSystemInfoArray); } var segment = segments[segmentIndex]; switch (segment) { case DirectorySegment directorySegment: { var filesToEmit = (options.EmitFiles && segmentIndex == segments.Length - 1) ? options.GetFiles(root).Where(file => directorySegment.MatchesSegment(file.Name, options.CaseSensitive)).Cast <FileSystemInfo>() : emptyFileSystemInfoArray; var dirSegmentItems = from directory in options.GetDirectories(root) where directorySegment.MatchesSegment(directory.Name, options.CaseSensitive) from item in Traverse(directory, segments, segmentIndex + 1, options) select item; return(filesToEmit.Concat(dirSegmentItems)); } case DirectoryWildcard _: { var filesToEmit = (options.EmitFiles && segmentIndex == segments.Length - 1) ? options.GetFiles(root).Cast <FileSystemInfo>() : emptyFileSystemInfoArray; // match zero path segments, consuming DirectoryWildcard var zeroMatch = Traverse(root, segments, segmentIndex + 1, options); // match consume 1 path segment but not the Wildcard var files = from directory in options.GetDirectories(root) from item in Traverse(directory, segments, segmentIndex, options) select item; return(filesToEmit.Concat(zeroMatch).Concat(files)); } default: return(emptyFileSystemInfoArray); } }
private static IEnumerable <FileSystemInfo> Traverse(List <DirectoryInfo> roots, Segment[] segments, TraverseOptions options) => new PathTraverserEnumerable(roots, segments, options);
internal static IEnumerable <FileSystemInfo> Traverse(DirectoryInfo root, Segment[] segments, TraverseOptions options) => Traverse(new List <DirectoryInfo> { root }, segments, options);
public PathTraverserEnumerable(List <DirectoryInfo> roots, Segment[] segments, TraverseOptions options) { this._originalRoots = roots; this._segments = segments; this._options = options; }