Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

重复文件查找工具(DuplicateFinder)

一个 Windows 桌面工具,核心差异点是文件夹级对比:找到重复文件后,可整文件夹地决定保留一侧、删除另一侧,而不是逐个文件挑挑拣拣。

版本:v0.15 · .NET Framework 4.8 + WPF · Win10/11 开箱即用,无需安装运行时。


环境要求

  • Windows 10 / 11(自带 .NET Framework 4.8)

构建与运行

方式一:直接运行(无需构建)

双击 publish/DuplicateFinder.exe

方式二:从源码构建

cd src
dotnet build -c Release

产物在 src/bin/Release/net48/DuplicateFinder.exe

方式三:发布(生成便携目录)

cd src
dotnet publish -c Release -r win-x64 -o ../publish

或直接在项目根目录运行:

.\build.ps1 -Publish

功能与用法

模式 A:单文件夹查重

  1. 模式选「单文件夹(复杂查重)」,选择根目录 A,点「开始扫描」。
  2. 左侧目录树只展示含重复文件的目录,括号内为自底向上累加的重复文件数。默认全部折叠,按需展开。
  3. 点击某个重复文件 → 右侧列出它的所有副本及其所在目录,以及每个目录与当前选中目录的文件夹相似度(Jaccard / IoU 计算,≥80% 高亮为「疑似整文件夹副本」)。
  4. 右侧文件支持 Ctrl/Shift 多选,底部「删除选中 (N)」批量删除。
  5. 工具栏支持忽略 0 字节文件(默认开启)、勾选「永久删除」跳过回收站(需二次确认)。

模式 B:双文件夹对比

  • 启动即双选:选择根目录 A + 根目录 B → 扫描后自动打开「目录对比」窗口,左右两栏各自展示重复文件,中间列出匹配副本对。
  • 模式 A 中触发:右键某文件选「对比所在文件夹」→ 对比该文件所在目录与副本所在目录(复用已算哈希,不重算)。

目录树交互

  • 点击文本(非小三角)也可展开/折叠目录。
  • 级联展开:若展开后目录无直接重复文件且仅含一个子目录,自动级联展开该子目录。
  • 右键菜单
    • 文件节点:打开文件 / 打开所在文件夹 / 删除。
    • 目录节点:打开文件夹 / 删除(四选项——依旧删除目录 / 仅删当前目录重复文件 / 删当前目录及子目录重复文件 / 取消)。若删除会导致某重复组全部副本消失,弹窗警告。

右侧面板交互

  • 文件列表右键:打开文件 / 打开所在文件夹 / 对比所在文件夹 / 删除。
  • 相似度列表:双击打开对应文件夹;右键可打开 / 对比 / 删除文件夹。删除文件夹时根据是否含子目录、相似度是否 100% 智能弹出不同确认对话框。
  • 键盘快捷键:选中文件后按 Del 直接移入回收站(永久删除模式下仍需确认)。

删除与动态收敛

  • 默认删除进回收站;勾选「永久删除」则直接删除(所有删除入口均追加二次确认)。
  • 删除后实时更新数据库;若某重复组被清理到只剩 1 个文件,该文件不再作为重复展示,对应目录计数与树节点自动收敛。
  • 目录树增量裁剪而非整树重建——删除后展开状态保留,大数据量不卡顿。

扫描结果持久化

  • 扫描结果保存到程序目录 dupfinder.db(SQLite)。
  • 启动时若存在数据库,弹窗询问是否加载上次结果。
  • 关闭时若存在数据库,弹窗询问是否保留(下次启动可恢复)。
  • 「清空缓存」按钮删除数据库并重置。

其他

  • 「并行度」默认 4,可自行修改(机械盘建议调低至 2)。
  • 扫描自动跳过符号链接 / junction / reparse point。
  • 无权限目录 / 被锁定文件记录日志后跳过,不中断扫描。
  • 工具栏右上角二维码,点击放大后可跳转网站。

设计要点

方面 实现
磁盘读取优化 先按文件大小分组,唯一大小瞬间判定孤立;≤1MB 全量 XxHash3;>1MB 仅读前 512K + 后 512K(最多 1MB)
哈希算法 System.IO.Hashing.XxHash3(seed=0),.NET 内置
相似度算法 Jaccard / IoU:重复文件数 / (|A|+|D|− 重复文件数) × 100
持久化 Microsoft.Data.Sqlite,支持断点续扫与对比复用
架构 MVVM(CommunityToolkit.Mvvm)+ WPF + .NET Framework 4.8
删除 SHFileOperation 进回收站;支持永久删除 + 二次确认

项目结构

DuplicateFinder/
├── src/                          # 源码
│   ├── DuplicateFinder.csproj    # net48 + WPF 项目文件
│   ├── App.xaml(.cs)             # 应用入口 + 全局异常处理
│   ├── MainWindow.xaml(.cs)      # 主窗口
│   ├── Models/                   # 数据模型(FileEntry, DupGroup, ScanSession, DirStat)
│   ├── Services/                 # 核心服务
│   │   ├── ScanEngine.cs         # 枚举 + 并行哈希调度
│   │   ├── HashCalculator.cs     # XxHash3 分块策略
│   │   ├── ScanRepository.cs     # SQLite + 内存缓存
│   │   ├── TreeBuilder.cs        # 目录树构建 + 累计统计
│   │   ├── TreeReconciler.cs     # 目录树增量裁剪
│   │   ├── ComparisonService.cs  # 单文件对比 + 文件夹相似度
│   │   ├── FileDeleteService.cs  # 删除服务(回收站/永久)
│   │   └── RecycleBin.cs         # SHFileOperation P/Invoke
│   ├── ViewModels/               # MVVM ViewModel
│   │   ├── MainViewModel.cs      # 主逻辑
│   │   ├── TreeItem.cs           # 树节点
│   │   └── CompareItem.cs        # 对比面板条目
│   ├── Views/                    # 视图
│   │   └── DualCompareWindow.xaml(.cs)  # 双目录对比窗口
│   └── Infrastructure/           # 基础设施
│       ├── ViewModelBase.cs      # MVVM 基类
│       ├── RelayCommand.cs       # ICommand 实现
│       ├── ScanProgress.cs       # 扫描进度
│       ├── Logger.cs             # 日志
│       └── CrashReporter.cs      # 全局异常兜底
├── test/                         # 核心算法端到端测试(41 项)
├── docs/                         # 文档
├── build.ps1 / build.sh          # 构建脚本
├── VERSION                       # 版本号
├── CHANGELOG.md                  # 版本历史
└── publish/                      # 发布产物

已知限制

  • 大文件哈希仅在内容前缀 + 中段(共 1MB)层面判定重复,存在极小碰撞概率(设计上可接受)。
  • 本项目为 WPF 桌面应用,仅支持 Windows;Linux / macOS 无法运行。

Duplicate File Finder (DuplicateFinder)

A Windows desktop tool whose core differentiator is folder-level comparison: after finding duplicate files, you can decide to keep one folder's copy and delete another folder's copy as a whole, rather than picking through files one by one.

Version: v0.15 · .NET Framework 4.8 + WPF · Works out of the box on Win10/11 with zero runtime installation.

Requirements

  • Windows 10 / 11 (comes with .NET Framework 4.8 pre-installed)

Build & Run

Option 1: Run directly (no build needed)

Double-click publish/DuplicateFinder.exe

Option 2: Build from source

cd src
dotnet build -c Release

Output: src/bin/Release/net48/DuplicateFinder.exe.

Option 3: Publish (portable directory)

cd src
dotnet publish -c Release -r win-x64 -o ../publish

Or from the project root:

.\build.ps1 -Publish

Features & Usage

Mode A: Single-folder dedup

  1. Select "Single folder", choose root directory A, click "Start Scan".
  2. The directory tree on the left shows only directories containing duplicates, with cumulative duplicate file counts in parentheses (bottom-up accumulation). All collapsed by default.
  3. Click a duplicate file → the right panel shows all its copies and their directories, plus folder similarity for each directory relative to the selected file's directory (Jaccard / IoU formula; ≥80% highlighted as "likely whole-folder copy").
  4. Right panel files support Ctrl/Shift multi-select; the bottom "Delete Selected (N)" button batch-deletes.
  5. Toolbar options: ignore zero-byte files (on by default), "Permanent delete" checkbox (skips Recycle Bin with double confirmation).

Mode B: Dual-folder comparison

  • Startup dual-select: Choose root A + root B → after scanning, a "Directory Comparison" window opens automatically with left/right trees and a middle match list.
  • Triggered from Mode A: Right-click a file and select "Compare Folder" → compares that file's directory with the copy's directory (reuses computed hashes, no re-scan).

Directory Tree Interactions

  • Click text (not just the arrow) to expand/collapse directories.
  • Cascade expand: If an expanded directory has no direct duplicate files and contains exactly one subdirectory, that subdirectory auto-expands recursively.
  • Right-click menu:
    • File node: Open file / Open folder / Delete.
    • Directory node: Open folder / Delete (4 options — Delete entire directory / Delete duplicates in current directory only / Delete duplicates in current directory and subdirectories / Cancel). Warns if deletion would eliminate all copies of any duplicate group.

Right Panel Interactions

  • File list right-click: Open file / Open containing folder / Compare folder / Delete.
  • Similarity list: Double-click to open the folder; right-click for Open / Compare / Delete folder. Smart confirmation dialogs based on whether the folder has subdirectories and whether similarity is 100%.
  • Keyboard: Press Del on a selected file to send to Recycle Bin (confirmation still required in permanent-delete mode).

Deletion & Dynamic Convergence

  • Default: send to Recycle Bin; check "Permanent delete" for direct deletion (all deletion paths add a second confirmation).
  • Database is updated in real-time after deletion; if a duplicate group drops to 1 remaining file, that file is no longer shown as a duplicate — directory counts and tree nodes converge automatically.
  • The directory tree uses incremental pruning instead of full rebuild — expanded state is preserved after deletion, and performance stays smooth even with large datasets.

Scan Result Persistence

  • Results are saved to dupfinder.db (SQLite) in the program directory.
  • On startup, if a database exists, a dialog asks whether to load the last scan.
  • On close, if a database exists, a dialog asks whether to keep it (for next-time recovery).
  • The "Clear Cache" button deletes the database and resets.

Miscellaneous

  • Concurrency defaults to 4; lower it (e.g., 2) for mechanical hard drives.
  • Symbolic links / junctions / reparse points are automatically skipped.
  • Permission-denied directories and locked files are logged and skipped without interrupting the scan.
  • A QR code in the top-right toolbar can be clicked to enlarge, then clicked again to open a website.

Design Highlights

Aspect Implementation
Disk I/O optimization Group by file size first; unique sizes are instantly isolated. ≤1MB: full XxHash3. >1MB: first 512KB + last 512KB only (1MB max read)
Hash algorithm System.IO.Hashing.XxHash3 (seed=0), built into .NET
Similarity formula Jaccard / IoU: matching / (|A| + |D| − matching) × 100
Persistence Microsoft.Data.Sqlite; supports resume-scan and comparison reuse
Architecture MVVM + WPF + .NET Framework 4.8
Deletion SHFileOperation for Recycle Bin; permanent delete with double confirmation

Project Structure

DuplicateFinder/
├── src/                          # Source code
│   ├── DuplicateFinder.csproj    # net48 + WPF project
│   ├── App.xaml(.cs)             # Entry point + global crash handler
│   ├── MainWindow.xaml(.cs)      # Main window
│   ├── Models/                   # Data models (FileEntry, DupGroup, ScanSession, DirStat)
│   ├── Services/                 # Core services
│   │   ├── ScanEngine.cs         # Enumeration + parallel hash scheduling
│   │   ├── HashCalculator.cs     # XxHash3 chunking strategy
│   │   ├── ScanRepository.cs     # SQLite + in-memory cache
│   │   ├── TreeBuilder.cs        # Directory tree + cumulative stats
│   │   ├── TreeReconciler.cs     # Incremental tree pruning
│   │   ├── ComparisonService.cs  # Single-file comparison + folder similarity
│   │   ├── FileDeleteService.cs  # Deletion service (Recycle Bin / permanent)
│   │   └── RecycleBin.cs         # SHFileOperation P/Invoke
│   ├── ViewModels/               # MVVM ViewModels
│   │   ├── MainViewModel.cs      # Main logic
│   │   ├── TreeItem.cs           # Tree node
│   │   └── CompareItem.cs        # Comparison panel item
│   ├── Views/                    # Views
│   │   └── DualCompareWindow.xaml(.cs)  # Dual-directory comparison window
│   └── Infrastructure/           # Infrastructure
│       ├── ViewModelBase.cs      # MVVM base class
│       ├── RelayCommand.cs       # ICommand implementation
│       ├── ScanProgress.cs       # Scan progress model
│       ├── Logger.cs             # Logger
│       └── CrashReporter.cs      # Global crash reporter
├── test/                         # Core algorithm E2E tests (41 assertions)
├── docs/                         # Documentation
├── build.ps1 / build.sh          # Build scripts
├── VERSION                       # Version file
├── CHANGELOG.md                  # Version history
└── publish/                      # Published output

Known Limitations

  • Large-file duplicate detection is based on content prefix + mid-section (1MB total read), with a negligible collision probability (acceptable by design).
  • This is a WPF desktop application, Windows only; does not run on Linux / macOS.

About

a green,lite,portable duplicate file finder. for windows.

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages