补给库的目录,是我自己搞乱的。
同一个文件三个备份,分别叫"最终版""最终版2""真的最终版";两个同名安装包大小差 200KB,我分不清哪个新。所以我写点东西,让它替我记着。
目标
扫目录、生成清单、顺手查重名。用 Kotlin,因为我的工具链本来就是它,处理文件集合写起来很舒服。
代码
import java.io.File
import java.security.MessageDigest
fun sha256(f: File): String {
val d = MessageDigest.getInstance("SHA-256")
f.inputStream().use { s ->
val buf = ByteArray(8192)
while (true) {
val n = s.read(buf)
if (n <= 0) break
d.update(buf, 0, n)
}
}
return d.digest().joinToString("") { "%02x".format(it) }
}
fun main(args: Array<String>) {
val dryRun = "--dry-run" in args
val root = File(args.firstOrNull { !it.startsWith("--") } ?: ".")
val groups = root.walkTopDown()
.filter { it.isFile }
.groupBy { it.extension.lowercase().ifBlank { "none" } }
.toSortedMap()
println("# 补给库清单\n")
groups.forEach { (ext, list) ->
println("## ." + ext + " — " + list.size + " 个\n")
list.sortedBy { it.name }.forEach { f ->
println("- " + f.relativeTo(root) + " · " + f.length() / 1024 + " KB")
if (dryRun) println(" - sha256 " + sha256(f).take(16))
}
println()
}
}
为什么这么写
walkTopDown()递归但不开线程,几千个文件完全够groupBy配toSortedMap,扩展名就不会随机乱序--dry-run先只打印不动手——我吃过亏,这个开关永远先开use { }保证流被关掉。写脚本最容易漏的就是这个
跑起来
kotlinc check.kt -include-runtime -d check.jar
java -jar check.jar ~/补给库 --dry-run
还没做的
按哈希找真正重复的文件(不只是同名),重叠的标出来,我手动删
输出改成 Markdown 表格,直接贴进补给库页面
跟上次清单对比,新增文件才提醒
一点想法
写脚本的快乐不在代码多漂亮,而在——从今往后这件事不归我管了。
我算过:手动整理一次半小时,一个月两次,一年十二小时。十二小时够我在公园坐四个下午。
给维修工的备注:带删除逻辑的脚本,先在副本目录跑。第一个把真实数据当测试数据的人,后来都成了谨慎的人。
—— 音葵
脚本还在跑,我去睡一会儿。醒了看看它有没有把「真的最终版」认成另一个文件。
【弹道计算 02】用 Kotlin 写个会自己干活的脚本
https://otogi.cn/archives/ddjs_02
评论