Skip to content

fix: Duplicate Finder says why a folder could not be scanned, and counts two names of one file once - #2950

Merged
laurentiu021 merged 1 commit into
mainfrom
fix/duplicate-finder-says-why-and-skips-hard-links
Oct 22, 2026
Merged

laurentiu021 merged 1 commit into
mainfrom
fix/duplicate-finder-says-why-and-skips-hard-links

Conversation

@laurentiu021

Copy link
Copy Markdown
Owner

Duplicate Finder had the failure-as-empty shape Disk Analyzer had until #2504, and it counted two names of one file as
two copies.

What changed

  • A folder that could not be scanned says why. DuplicateFileService.ScanAsync returns a DuplicateScan: the
    groups, or a ScanFailure (NotFound, IsLink, Unreadable, Excluded), shaped like Disk Analyzer's Analysis.
    A missing folder, a link, a root Windows would not list (C:\System Volume Information, for one) and a root the
    walk leaves out all came back as an empty list, which the tab reported as "No duplicates found". The root is now
    listed on its own, so only it fails the scan: a folder below it that cannot be listed is still skipped. The tab
    shows the reason in its empty state and on the status line, and a scan that could not run is not counted as one.
  • Two names of one file are not two copies. The full hash asks the handle it reads for the file's identity and
    skips another name of a file already hashed, so a hard link leaves the group and the space wasted. Before, a 64 KB
    file with a second name was a group of two with 65,536 bytes wasted.
  • Helpers/FileIdentity holds the volume serial number and the 128-bit file ID from
    GetFileInformationByHandleEx(FileIdInfo), which stays unique on ReFS, where the 64-bit index
    GetFileInformationByHandle returns does not. Its LinksOf is the hard-link count File Shredder refuses a shred on,
    moved from the shredder's own copy of BY_HANDLE_FILE_INFORMATION; the shredder's behaviour is unchanged.
  • The two reasons Disk Analyzer and Duplicate Finder give word for word (a folder that is gone, one Windows would
    not list) are constants in ViewModelBase, which both use.
  • CHANGELOG 1.130.57, README (Duplicate Finder), ARCHITECTURE (DuplicateFileService, Helpers/FileIdentity).

Tests

  • Each refusal: a missing, empty and null root (NotFound), a root that is a link (IsLink), a root whose listing
    throws access denied, an I/O error (Unreadable) or not found (NotFound), and a $Recycle.Bin picked as the root
    (Excluded). A folder below the root that cannot be listed is skipped and the rest scanned.
  • Hard links, built with Symlinks.RequireHardLink: two names of one file are no group; a copy beside them is one
    group of two with one file wasted. FileIdentityTests checks that two names share an identity and two links, and a
    copy has its own identity and one link.
  • The tab: a scan of a folder that is gone says it could not be scanned and why, a scan that works after it says
    what it found, and every failure has its own explanation.

Each test failed against the defect it pins: with each failure returned as no failure, the excluded root scanned, a
subfolder that cannot be listed failing the scan, the identity check removed, every file given the same ID, the
shredder's link count ignored, and the tab ignoring the failure.

Closes #2823.

…nts two names of one file once

- DuplicateFileService.ScanAsync returns a DuplicateScan: the groups, or why the chosen folder could not be scanned
  (NotFound, IsLink, Unreadable, Excluded), shaped like Disk Analyzer's Analysis. A missing folder, a link, a root
  Windows would not list and a root the walk leaves out all came back as an empty list, which the tab reported as
  "No duplicates found". The root is listed on its own, so a folder below it that cannot be listed is still skipped.
- The full hash asks the handle it reads for the file's identity and skips another name of a file already hashed.
  Two names of one file were a group with the file's size wasted, though deleting either frees nothing.
- FileIdentity, in Helpers, holds the volume serial number and the 128-bit file ID from
  GetFileInformationByHandleEx(FileIdInfo), which is unique on ReFS too, and LinksOf, which File Shredder now reads
  its hard-link count through instead of its own copy of BY_HANDLE_FILE_INFORMATION.
- The tab shows the reason in its empty state and on the status line, and the two reasons it shares with Disk
  Analyzer word for word live once, in ViewModelBase.
@laurentiu021
laurentiu021 merged commit d2bae2a into main Oct 22, 2026
6 checks passed
@laurentiu021
laurentiu021 deleted the fix/duplicate-finder-says-why-and-skips-hard-links branch October 22, 2026 06:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Duplicate Finder — a folder it could not read reports "No duplicates found", and two names of one hard-linked file count as a duplicate

1 participant