|
|
磁盘清道夫sdcard 垃圾一键清理
- /**
- * 案例32:磁盘清道夫——/sdcard 垃圾一键清理
- *
- *
- * 为什么有用:云手机/模拟器盘小,截图、安装包、缓存堆几个月就满盘;
- * 这脚本不是演示玩具,运维的人真拿来一天跑一次。
- * 原理:adb.exec 跑 df(磁盘用量)/du(大目录扫描)/find(按规则找垃圾)/rm(删)
- * 四条 shell,全部以 App 自身 uid 执行,免 root(案例30已锤 adb.exec 通道)。
- * 释放总量直接对比清理前后 df,不逐文件算账,又快又准。
- * 安全带:实删=false 默认演练,只列清单不动手;确认无误改 true 才真删。
- * 只碰三类垃圾:老截图 / 残留APK / 老压缩包,绝不动通讯录、照片、App数据。
- *
- * 用法:直接运行看演练报告 → 检查列出的文件没问题 → 实删 改 true 再跑一次。
- * 可配合案例26定时闭环,每天凌晨自动清盘。
- */
- // ========== 配置区 ==========
- var 实删 = false; // ★演练开关:false=只列清单;true=真删
- var 截图保留天数 = 7; // DCIM 里比这更早的截图算垃圾
- var 压缩包保留天数 = 3; // Download 里比这更早的 zip 算垃圾
- var 扫描大目录 = true; // 是否 du 扫 /sdcard 顶层大目录(慢机可能要等几十秒)
- var 大目录阈值KB = 51200; // 只列超过 50MB 的目录
- // 垃圾规则(toybox find 语法:-type f -name 样式 -mtime +天数)
- var 规则列表 = [
- { 名: "老截图", 目录: "/sdcard/DCIM", 找: "-type f -name "*.jpg" -mtime +" + 截图保留天数 },
- { 名: "残留APK", 目录: "/sdcard/Download", 找: "-type f -name "*.apk"" },
- { 名: "老压缩包", 目录: "/sdcard/Download", 找: "-type f -name "*.zip" -mtime +" + 压缩包保留天数 }
- ];
- // ========== adb 通道(案例30锤死:返回JSON包 {errorMsg, success}) ==========
- function adb跑(命令) {
- try {
- var 数据 = JSON.parse(adb.exec(命令, false));
- return {
- 成: 数据.success == null ? "" : ("" + 数据.success),
- 错: 数据.errorMsg == null ? "" : ("" + 数据.errorMsg).trim()
- };
- } catch (e) { return { 成: "", 错: "exec异常 " + e }; }
- }
- // ========== df:磁盘用量(取最后一行数字列:总/已用/可用/使用率) ==========
- function 查df() {
- var r = adb跑("df -k /sdcard");
- var m = r.成.match(/(\d+)\s+(\d+)\s+(\d+)\s+(\d+)%/);
- if (m == null) return null;
- return {
- 总MB: Math.round(m[1] / 1024),
- 已用MB: Math.round(m[2] / 1024),
- 可用MB: Math.round(m[3] / 1024),
- 用率: m[4] + "%"
- };
- }
- // ========== du:顶层大目录排行(输出行"KB数+Tab+路径",JS里排序) ==========
- function 扫大目录() {
- var r = adb跑("du -d 1 -k /sdcard");
- var 行 = r.成.split("\n");
- var 表 = [];
- for (var i = 0; i < 行.length; i++) {
- var m = 行[i].match(/^(\d+)\s+(\/\S.*)$/);
- if (m != null) {
- var kb = parseInt(m[1], 10);
- if (kb >= 大目录阈值KB) 表.push([m[2], kb]);
- }
- }
- 表.sort(function (a, b) { return b[1] - a[1]; });
- return 表;
- }
- // ========== find:按规则找垃圾文件清单 ==========
- function 找垃圾(规则) {
- var r = adb跑("find " + 规则.目录 + " " + 规则.找);
- if (r.成 === "") return [];
- var 行 = r.成.split("\n");
- var 表 = [];
- for (var i = 0; i < 行.length; i++) {
- var s = 行[i].trim();
- if (s.indexOf("/sdcard") === 0) 表.push(s); // 过滤掉报错行,只留真路径
- }
- return 表;
- }
- // ========== rm:删单个文件 ==========
- function 删文件(路径) {
- var r = adb跑("rm -f " + 路径);
- return r.错 === "";
- }
- // ========== 主流程 ==========
- function main() {
- printl("=== 案例32 磁盘清道夫 启动:模式=" + (实删 ? "★实删" : "演练(只报不删)") + " ===");
- var 前df = 查df();
- if (前df == null) {
- printl("❌ df 都跑不动,adb.exec 通道异常:" + adb跑("df -k /sdcard").错);
- return;
- }
- printl("💾 清理前:总 " + 前df.总MB + "MB | 已用 " + 前df.已用MB + "MB(" + 前df.用率 + ") | 可用 " + 前df.可用MB + "MB");
- if (扫描大目录) {
- printl("🔎 du 扫 /sdcard 顶层大目录(≥" + Math.round(大目录阈值KB / 1024) + "MB),慢机稍等...");
- var 大 = 扫大目录();
- if (大.length === 0) printl(" (没扫到大目录,不影响清理)");
- for (var i = 0; i < 大.length && i < 8; i++) {
- printl(" " + (i + 1) + ". " + 大[i][0] + " ≈" + Math.round(大[i][1] / 1024) + "MB");
- }
- }
- var 总可清 = 0;
- for (var j = 0; j < 规则列表.length; j++) {
- var 规则 = 规则列表[j];
- var 垃圾 = 找垃圾(规则);
- 总可清 += 垃圾.length;
- printl("🧹 [" + 规则.名 + "] 命中 " + 垃圾.length + " 个 ← " + 规则.目录);
- for (var k = 0; k < 垃圾.length && k < 5; k++) printl(" " + 垃圾[k]);
- if (垃圾.length > 5) printl(" ...其余 " + (垃圾.length - 5) + " 个省略");
- if (实删) {
- var 删成 = 0, 跳过 = 0;
- for (var t = 0; t < 垃圾.length; t++) {
- if (垃圾[t].indexOf(" ") >= 0) { 跳过++; continue; } // 带空格路径跳过,防参数劈叉
- if (删文件(垃圾[t])) 删成++;
- }
- printl(" ✅ 实删 " + 删成 + " 个" + (跳过 > 0 ? ",跳过带空格 " + 跳过 + " 个" : ""));
- }
- }
- if (!实删) {
- printl("📋 演练完毕:共可删 " + 总可清 + " 个文件。");
- printl("💡 检查上面清单没误伤 → 把 实删 改 true 再跑一次就真清盘");
- } else {
- var 后df = 查df();
- if (后df != null) {
- var 释放 = 后df.可用MB - 前df.可用MB;
- printl("💾 清理后:可用 " + 后df.可用MB + "MB(" + 后df.用率 + ")");
- printl("🎉 本次释放 " + (释放 > 0 ? 释放 + " MB" : "不足 1MB(删的都是小文件)"));
- }
- }
- printl("=== 案例32 收工 ===");
- }
- main();
复制代码
|
|