Skip to content

Latest commit

 

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dedup — 本地文件去重 / 相似图片查找 CLI

一个用 Go 编写的命令行工具,用来:

  1. 精确去重:按文件内容(SHA-256)找出完全相同的文件;
  2. 相似图片查找:用感知哈希(dHash)找出肉眼几乎一样的图片(即使被压缩 / 改尺寸 / 调了亮度)。

全部使用 Go 标准库 + Windows API 实现,零第三方依赖,编译出来是单个二进制文件,可直接分发。

特性

  • 🔍 精确去重(SHA-256 内容哈希),并发计算,自动按可回收空间排序
  • 🖼️ 相似图片查找(64 位 dHash + 汉明距离),支持 JPG/PNG/GIF/BMP/WebP/TIFF
  • 📊 实时进度条(stderr,不污染 stdout 报告)+ 按扩展名统计(文件数 / 总大小)
  • 📑 CSV 导出:把重复 / 相似结果导出为表格,便于二次处理
  • 🗑️ 安全删除:把重复文件移入系统回收站(绝不 rm)
    • -delete:精确重复,每组保留一个
    • -delete-similar:相似图片,保留每组代表图,删除前二次确认
    • 两者均支持 -dry-run 预览与 -yes 跳过确认
  • 🌐 Web 可视化界面:dedup serve 启动本地服务,浏览器里选目录、看实时进度、点缩略图、一键安全删除(详见下文)
  • 📄 三种报告格式:终端文本 / JSON / HTML(HTML 带图片缩略图)
  • ⚡ 并发扫描与哈希(worker pool),可指定 -workers
  • 🧹 忽略规则:隐藏文件、指定目录(.git / node_modules)、最小/最大文件大小、修改时间、扩展名过滤

安装

从源码

git clone https://github.com/kll237/dedup.git
cd dedup
go build -o dedup .

go install

go install dedup@latest

使用

# 1) 找出某目录下所有精确重复文件(默认 text 报告,输出到终端)
dedup -path "D:/Photos"

# 2) 同时查精确重复 + 相似图片
dedup -path "D:/Photos" -mode both

# 3) 只查相似图片,汉明阈值调到 8(更严格)
dedup -path "D:/Photos" -mode image -threshold 8

# 4) 生成 HTML 报告(带缩略图),写到文件
dedup -path "D:/Photos" -format html -out report.html

# 5) 机器可读的 JSON 报告
dedup -path "D:/Photos" -format json -out report.json

# 6) 导出 CSV(列:type, group, path, size_bytes, sha256, phash, hamming_distance)
dedup -path "D:/Photos" -csv report.csv

# 7) 预览将要删除的重复文件(不真正删除)
dedup -path "D:/Photos" -delete -dry-run

# 8) 真正把重复副本移入回收站(每组保留按路径排序的第一个)
dedup -path "D:/Photos" -delete

# 9) 相似图片安全删除,删除前会要求确认;-yes 可跳过确认
dedup -path "D:/Photos" -delete-similar
dedup -path "D:/Photos" -delete-similar -yes

Web 可视化界面

不想敲命令行?项目内置了一个零依赖的 Web 仪表盘:后端直接复用扫描 / 哈希 / 报告 / 回收站逻辑,前端用 go:embed 打包进二进制,无需任何额外依赖或前端构建步骤。

# 启动(默认 http://localhost:8080,自动打开浏览器)
dedup serve

# 指定端口 / 关闭自动打开浏览器
dedup serve -addr 127.0.0.1:9000 -open=false

打开浏览器后的操作:

  1. 在「扫描路径」填入要扫的目录(如 D:/Photos,或项目自带示例 demo/input);
  2. 选择模式(精确 / 相似图片 / 两者)、相似阈值、大小过滤;
  3. 点「开始扫描」,进度条实时刷新(扫描 → 内容哈希 → 感知哈希);
  4. 结果以卡片展示:统计概览、按扩展名统计、精确重复组、相似图片组(每张带缩略图与汉明距离);
  5. 点「删除副本」按钮,弹窗二次确认后把额外副本移入回收站(保留每组一个,可在回收站找回)。

所有能力(安全删除、并发、过滤规则)与命令行完全一致。

serve 子命令参数

参数 说明 默认
-addr serve 子命令的监听地址 :8080
-open 启动后自动打开浏览器 true

常用参数

参数 说明 默认
-path 要扫描的路径(可多次指定),也可用位置参数 —
-mode exact / image / both both
-format text / json / html text
-out 报告输出文件(默认 stdout) 空
-csv CSV 导出文件(与 -out 独立的扁平表格) 空
-threshold 相似图片汉明距离阈值(0-64,越小越严格) 10
-min-size / -max-size 文件大小过滤,如 1KB / 10MB 0
-min-time / -max-time 按修改时间过滤:绝对日期 2024-01-01,或相对值 90d/12w/6m/1y(-min-time 保留最近 N 天内的文件,-max-time 保留早于 N 天前的文件) 空
-workers 并发数(默认 = CPU 核数) 0
-skip-hidden 跳过隐藏文件和目录 true
-ignore 跳过的目录名,逗号分隔 .git,.node_modules
-delete 把精确重复的额外副本移入回收站(保留每组一个) false
-delete-similar 把相似图片的额外副本移入回收站(保留代表图,需确认) false
-yes 跳过删除前的二次确认 false
-dry-run 仅预览待删除文件,不实际删除 false

效果演示

全部截图与输出均来自实际运行:对 demo/input 下重复文本与图片执行 dedup 得到,可复现(见末尾命令)。

1) 安全删除预览 -delete-similar -dry-run

[相似图片] 以下副本将被移入回收站(保留每组代表图):
  - …\demo\input\b_near.jpg
[dry-run] 仅预览,未实际删除。

运行时会在 stderr 打印实时进度条(不影响 stdout 报告):

计算内容哈希  [############################] 8/8 100%
计算感知哈希  [############################] 3/3 100%

2) HTML 报告

dedup -format html 生成的 demo/output/report.html 内嵌了图片缩略图(base64)。用浏览器打开它即可截图:

HTML 报告效果

dedup -path demo/input -mode both -format html -out demo/output/report.html

3) Web 可视化工作台(dedup serve)截图

dedup serve 启动一个零依赖的 Web 仪表盘(前端资源通过 go:embed 打包进二进制),支持:选择扫描路径、按大小 / 修改时间过滤、调整相似阈值、查看精确重复、相似图片、扩展名统计、清理建议,以及一键删除 / 移入回收站。

模块 截图 说明
工作台首页 工作台首页 首次进入,默认扫描路径 demo/input,可一键开始扫描
扫描进度 扫描进度 实时显示内容哈希与感知哈希计算进度
扫描概览 扫描概览 扫描完成后展示文件数、重复组、相似图片组、可节省空间与扩展名分布
精确重复 精确重复 按 SHA-256 分组的重复文件,可删除多余副本
相似图片 相似图片 按 dHash 汉明距离找到的近重复图片,展示缩略图与哈希距离
扩展名统计 扩展名统计 按扩展名聚合文件数与大小,识别空间占用大户
清理建议 清理建议 基于规则推荐的临时文件、大文件、旧文件、重复文件
长期未使用文件 长期未使用文件 按「超过 N 天未修改」规则识别出的视频等长期未使用文件
删除确认 删除确认 一键清理前的二次确认弹窗,删除文件会移入回收站
高级过滤 高级过滤 展开「高级建议设置」,支持自定义长期未用、大文件阈值等参数

完整产物都在仓库 demo/output/ / demo/:

文件 说明
demo/output/report.html HTML 报告(带缩略图,浏览器打开即可截图)
demo/output/report.csv CSV 导出
demo/output/stdout.txt 完整终端扫描输出原文
demo/output/delete_similar_preview.txt 删除预览原文
demo/TEST_OUTPUT.txt go test -v ./... 测试通过输出

单元测试

ok  	dedup/hash      (cached)
ok  	dedup/imageph   (cached)
ok  	dedup/report    0.165s
ok  	dedup/scan      (cached)

完整 9 个用例输出见 demo/TEST_OUTPUT.txt;CI 在每次 push 时自动运行。

如何复现

cd demo
bash run.sh        # Linux/macOS
# Windows: run.bat

脚本会重新构建并跑出上面全部产物(样例数据已随仓库提交在 demo/input/)。

架构

main.go          命令行解析、流程编排、删除决策
├── scan/        递归遍历文件系统,应用过滤规则
├── hash/        内容哈希(SHA-256)+ 并发分组(精确去重)
├── imageph/     图片解码 → 灰度 → 缩放 → dHash → 并查集分组(相似图片)
├── report/      文本 / JSON / HTML 三种报告渲染(HTML 内嵌缩略图)
├── trash/       调用系统回收站(Windows: SHFileOperationW;其他: gio/trash-put)
├── web/         零依赖 Web 仪表盘(`dedup serve`),前端用 go:embed 打包
└── result/      跨包共享的数据结构

关键设计

  • 精确去重:hash.FindExact 用固定数量的 goroutine 并发计算 SHA-256,结果按内容哈希归组,每组文件数 > 1 即为重复。
  • 相似图片:先算每张图的 64 位 dHash 指纹,再用**并查集(union-find)**把汉明距离 ≤ 阈值的图片合并成组,时间复杂度 O(n²),对常规相册规模足够快。
    • dHash 流程:解码 → 灰度化 → 缩放到 9×8 → 比较相邻像素亮度 → 得到 64 位指纹。对缩放、压缩、轻微调色鲁棒。
  • 安全删除:Windows 下通过 shell32.dll!SHFileOperationW(FOF_ALLOWUNDO)把文件移入回收站,可还原;绝不调用 os.Remove。-delete 针对精确重复(保留每组一个,无需确认即可执行预览),-delete-similar 针对相似图片(非逐字节相同,删除前强制二次确认,可用 -yes 跳过);两者都有 -dry-run 预览。

性能

  • 内容哈希瓶颈在磁盘 I/O,并发读取可充分利用多核 / 多磁盘。
  • 相似图片为 O(n²) 两两比较;对上万张图片建议在 CI/脚本里分批,或提高 -threshold 先用精确哈希去重减少候选。

技术博客 / 实现解析

想了解背后的算法与工程取舍,可以看(在线版 ↓ / 仓库版在 docs/):

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages