Skip to content

Allow opting out of following directory links (reparse points / symlinks) during recursive file-system enumerations #52666

@mklement0

Description

@mklement0

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.Directory is not a general solution, because you may still want the link itself to be enumerated.

Proposed API

Add a new bool DoNotFollowDirectoryLinks property FollowDirectoryLinks 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-System.IO

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions