-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Background and Motivation
Related to #24271.
Especially on Unix-like platforms, use of (directory) symlinks (symbolic links) is common.
If, while recursively enumerating a directory (subtree) directory, symlinks to directories are encountered, these symlinks are currently invariably followed, so that the enumeration includes the content of the linked directory as well.
However, you may not want this behavior:
- because it can substantially expand the scope of the enumeration
- it can result in cycles, which:
- in the benign case can cause re-enumeration of already enumerated directories
- in the pathological case can result in infinite enumeration (infinite loop).
For this reason, standard Unix utilities such as find require opt-in in order for directory symlinks to be followed.
While an opt-in isn't an option anymore for reasons of backward compatibility, an opt-out should be considered.
Note:
-
The opt-out should apply to all types of directory links, which additionally includes junctions and volume mount points on Windows.
-
The opt-out should only apply to directory links encountered during enumeration, not to the input path (that is, a directory link as the starting point of an enumeration should always be followed).
-
Using
AttributesToSkip = FileAttributes.ReparsePoint | FileAttributes.Directoryis not a general solution, because you may still want the link itself to be enumerated.
Proposed API
Add a new bool DoNotFollowDirectoryLinks propertyFollowDirectoryLinks property that defaults to true (see @Joe4evr's comment below) to the System.IO.EnumerationOptions class.
The property name is negotiable. I avoided the term "ReparsePoint" as a generalization (given that it is NTFS-specific) and chose "Link" instead (without including the word "Symbolic", given that the behavior wouldn't be limited to additional link types beside symbolic links).
Update: @carlossanlop proposes FollowSymbolicLinks instead.
Usage Examples
// E.g., on macOS, where /System/Library contains a lot of directory symlinks.
Directory.EnumerateDirectories(
"/System/Library",
"*",
new EnumerationOptions { RecurseSubdirectories = true, FollowDirectoryLinks = false, AttributesToSkip = 0 }
);Alternative Designs
Perhaps introduce a RecurseSubdirectoriesExceptLinks property instead, mutually exclusive with RecurseSubdirectories, which, however, requires enforcement at runtime.
Risks
None that I'm aware of.