Skip to content

Stats "Duplicate files by extension" credits a whole group to one random copy's extension, so the breakdown changes between runs and disagrees with "Duplicate files" #146

Description

@matt-edmondson

What's wrong

In FileDeduplicator/Verbs/Stats.cs (around lines 78-88), the extension breakdown reads the extension from group.Files[0] and adds the whole group.Files.Count to that one extension:

string ext = System.IO.Path.GetExtension(group.Files[0].WeakString);
...
extensionCounts[ext] = count + group.Files.Count;

This causes three problems:

  1. Wrong attribution. When identical content exists under different extensions, every copy is counted under one of them. For example, photo.jpg, photo-copy.png and backup.bak all land under a single extension.
  2. Nondeterministic output. Files[0] is whichever copy comes first in the group built from the parallel hash (FileHasher.HashFiles fills a ConcurrentDictionary, which GroupByHash then groups). The same tree can report a different extension on every run.
  3. Inconsistent totals. The breakdown counts the kept copy too. Its totals exceed the "Duplicate files" line printed just above it, which counts only the redundant copies.

Repro

Put the three files above, with identical content, in a temp directory, then run ConsoleCapture.Run(new Stats { PathString = root }) three times.

  • Actual: the runs print .png: 3 file(s), .jpg: 3 file(s), .jpg: 3 file(s), while "Duplicate files" says 2.
  • Expected: a stable per-file breakdown whose total matches "Duplicate files".

Suggested fix

Iterate the files in each group and count each file's own extension. To stay consistent with "Duplicate files" and "Wasted space", count only the copies that would be removed, i.e. skip Deduplicator.SelectFileToKeep(group.Files).

Acceptance criteria

  • A test with mixed-extension duplicates gets the same breakdown on repeated runs, with each extension counted once per redundant file, and the breakdown sums to the "Duplicate files" count.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingreadyFully specified; implement as written

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions