Skip to content

Multi-part extensions (.tar.gz) defeat numbered-copy detection #9

Description

@fahadsiddiqui

Summary

Numbered-copy detection strips only the final extension, so it fails completely on multi-part extensions like .tar.gz. The copy scores identically to the original, and which one survives becomes a coin flip.

Reproduction

Measured calculateFilePriority:

filename priority expected
archive.tar.gz 0 0
archive (1).tar.gz 0 ~1001

Compare with the single-extension case, which works:

| invoice.pdf | 0 |
| invoice (1).pdf | 1001 |

Root cause

main.go:28:

nameWithoutExt := strings.TrimSuffix(name, filepath.Ext(name))

filepath.Ext("archive (1).tar.gz") returns .gz, leaving archive (1).tar. The numbered patterns at main.go:32-34 are all $-anchored, so the trailing .tar prevents any match.

Affects .tar.gz, .tar.bz2, .tar.xz, .tar.zst, and any other compound suffix.

Consequence

archive.tar.gz and archive (1).tar.gz land in the same duplicate group with equal priority, which is exactly the ambiguous-tie situation described in #7 — except here the tool had the evidence to decide correctly and threw it away.

Related edge case

filepath.Ext(".bashrc") returns .bashrc (the leading dot is the final dot), so nameWithoutExt becomes the empty string for any dotfile without a second extension. Scoring currently returns 0 for those by luck rather than by design; worth pinning down with a test either way.

Expected behaviour

Detect the copy marker without depending on correct extension splitting — match \((\d+)\) immediately before the first extension separator, or strip known compound extensions before scoring.

Test to write first

  • archive (1).tar.gz scores as a numbered copy.
  • archive.tar.gz scores 0.
  • The invoice.pdf / invoice (1).pdf pair keeps working (regression guard).
  • .bashrc and .gitignore score 0 and do not panic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions