# Macos Disk Cleanup

> macOS 磁盘（存储空间）占用诊断与安全清理。适用于「电脑内存满了」「硬盘满了」「清理不出来」「看不见的地方占空间」等场景。含分层扫描法（规避 du 被 SIGKILL）、微信/企业微信/飞书/WPS 等国产 App 的真实数据目录、以及「移入废纸篓而非删除」的安全清理协议。

- Skill: `paloma333/macos-disk-cleanup` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add paloma333/macos-disk-cleanup`
- Raw SKILL.md: https://api.skillmd.com/api/skills/paloma333/macos-disk-cleanup/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: Paloma333 (https://skillmd.com/u/paloma333)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/paloma333/macos-disk-cleanup

---


# macOS 磁盘占用诊断与安全清理

## 第 0 步：先纠正概念

用户说"内存满了"，**99% 是磁盘空间不足**，不是 RAM。先跑 `df -h` 确认，并明确告诉用户这个区别——因为"关软件"解决不了磁盘问题。

```bash
df -h / /System/Volumes/Data
diskutil apfs list | head -60          # 看各卷占用（Preboot/VM/Recovery 也要看）
diskutil info / | grep -i "Container Free Space"
tmutil listlocalsnapshots /            # Time Machine 本地快照是常见的"空间黑洞"
```

本地快照过多是很多人"空间莫名消失"的真凶，务必先排除。

## 第 1 步：分层扫描（关键技巧）

**绝对不要**直接 `du -sh ~/*` —— 主目录文件数太多会被 SIGKILL（exit code 137），白等几分钟。

正确做法是**分层、分目录、逐个扫**，每层单独一次调用（可加 `-x` 限制不跨文件系统）：

```bash
# 第一层：系统级
du -sh -x /Users/* /private/* /Library /usr /Applications /opt  2>/dev/null | sort -rh | head -15

# 第二层：用户 Library 的主要子目录
du -sh -x ~/Library/Caches ~/Library/Containers ~/Library/"Group Containers" \
        ~/Library/"Application Support" ~/Library/Logs ~/Library/Developer 2>/dev/null

# 第三层：可见目录（逐个，别用通配）
for d in Desktop Documents Downloads Movies Pictures Music; do
  printf "%-12s " "$d"; du -sh -x ~/"$d" 2>/dev/null | cut -f1
done

# 第四层：隐藏缓存
du -sh -x ~/.Trash ~/.cache ~/.npm ~/.docker ~/.conda ~/.vscode ~/.workbuddy 2>/dev/null | sort -rh
```

继续往下拆时也用同样方式：`du -sh -x "$DIR"/* | sort -rh | head -20`。

**收尾必做**：各层加总要能和 `df` 的已用量对平。对不平才说明还有隐藏项，再针对性找。对平了就可以告诉用户"没有神秘黑洞"——这句话本身就是最大的价值。

## 第 2 步：国产 App 数据目录速查（真正的"看不见的地方"）

这些 App 本体通常只有 1–2GB，但沙盒数据能到几十 GB，且访达默认不显示全路径。

### 微信 WeChat 4.x（最常见的第一大元凶）

```
~/Library/Containers/com.tencent.xinWeChat/Data/Documents/xwechat_files/<wxid>/msg/attach   # 图片，通常最大
                                                                    .../msg/video    # 视频
                                                                    .../db_storage   # 聊天记录数据库
                                                                    .../business     # 小程序数据
                                                                    .../msg/file     # 传输文件
```
- 注意：旧版路径是 `.../WeChat Files/`，4.x 已改为容器内 `xwechat_files/`
- `msg/attach` 下按**会话哈希**（32 位十六进制）命名，无年月结构
- 取时间分布要逐个目录 `stat -f "%Sm" -t "%Y-%m"`，不能靠目录名

### 企业微信 WeCom
```
~/Library/Containers/com.tencent.WeWorkMac/Data/Documents/cefcache/wew_<企业ID>        # Chromium 缓存
                                          .../Profiles/<32位hex>/Messages1/Session.db   # ⚠️ 聊天记录主体
                                          .../Profiles/<32位hex>/Publishsys/pkg         # 前端资源包
                                          .../Data/Library/Application Support/WXWork/Data/<企业ID>
```

### 飞书 Lark
```
~/Library/Application Support/LarkShell/aha/users/<账号ID>/profile_explorer/Service Worker/CacheStorage  # 网页缓存，通常最大
~/Library/Application Support/LarkShell/update          # 旧版本安装包
~/Library/Application Support/LarkShell/sdk_storage     # SDK 本地状态（不是纯缓存）
~/Library/Caches/LarkShell
~/Library/Mobile Documents/iCloud~com~bytedance~ee~lark
```

### WPS Office
```
~/Library/Containers/com.kingsoft.wpsoffice.mac/Data/Library/Application Support
```

### 卸载后的残留位置（通用清单）
```
~/Library/Application Support/<App>
~/Library/Caches/<bundle-id>*
~/Library/Preferences/<bundle-id>*.plist
~/Library/HTTPStorages/<bundle-id>
~/Library/Saved Application State/<bundle-id>.savedState
/private/var/folders/*/*/C/<bundle-id>*        # 最容易漏！普通清理工具找不到
```

搜索残留用 bundle-id 关键字：
```bash
find ~/Library ~/private/var/folders/nz -maxdepth 3 \( -iname "*lark*" -o -iname "*feishu*" \) 2>/dev/null
```

## 第 3 步：风险分级（决定"能不能删"）

**永远不要**把"软件数据"一刀切当成"缓存"。必须分级：

| 级别 | 判断依据 | 例子 |
|---|---|---|
| 🟢 纯缓存 | 在 `Caches/` 下、Service Worker CacheStorage、ShaderCache、日志、旧版本安装包 | 可再生，删了无影响 |
| 🟡 依赖云端 | 数据在服务器，本地只是副本 | 个人微信/飞书的聊天记录 |
| 🔴 本地独有 | **本地 SQLite 数据库**、离线标记文件、未同步草稿、本地会议录制 | 删了可能永久丢失 |

### 关键差异（务必区分，别搞混）

- **个人微信 / 飞书**：聊天记录主体在服务器，本地大头是网页缓存 → 删缓存安全
- **企业微信**：聊天记录主体在**本地 `Session.db`**，服务器仅按企业保留策略存部分 → **删了就没了**

判断"删除代价"时必问：**重新登录能不能取回来？** 如果不能（比如已离职、账号被停用），本地就是唯一副本。

### 其他易丢项
- 输入框草稿、飞书"离线文件"标记的文件
- 本地搜索索引（删后需重建，短期搜不到历史）
- `Caches/Files` 这类"文件缓存"（重新下载需要账号still有效）

## 第 4 步：清理执行协议

### 移入废纸篓，不要 rm

```bash
# Finder 自动化在本机常被系统拒绝（-10004 privilege violation），别依赖 osascript
osascript -e 'tell application "Finder" to delete (POSIX file "/path" as alias)'  # 可能失败

# 可行方案：mv 到 ~/.Trash 的自建子目录（同卷 rename，瞬间完成，不需要额外空间）
TRASH_DIR="$HOME/.Trash/清理备份_$(date +%Y%m%d)"
mkdir -p "$TRASH_DIR"
mv "$SRC" "$TRASH_DIR/<语义化名称>"
```

注意：
- `ls ~/.Trash` 可能被沙箱拒绝（Operation not permitted），**靠 `mv` 返回码 + 目标存在性校验**来判断成功
- basename 会冲突（如 `Caches/Adobe` 和 `Logs/Adobe`），用**自定义语义化目标名**区分
- 同卷移动**不释放空间**，必须清空废纸篓才真正腾出——要主动告诉用户，否则用户会以为没生效

### 处理运行中的 App
- 先 `pgrep -f "<AppName>"` 确认是否运行
- 运行中的 App：其缓存会被立刻重建，白费力气；WorkBuddy/编辑器类正在使用的缓存目录**不要动**（用 `stat` 看 mtime 判断是否活跃）
- 建议让用户先退出 App 再清理

### 执行前核验
```bash
# 检查待清理项是否存在、当前体积（体积会变，别用旧数据）
for p in <path1> <path2>; do
  [ -e "$p" ] && printf "%-40s %s\n" "$(basename "$p")" "$(du -sh -x "$p" 2>/dev/null | cut -f1)"
done
```

### 执行后核验（必做）
1. 源路径确实不存在
2. 废纸篓备份区体积 = 预期
3. **保留项完好**（这一步最重要，别只检查删掉的）

## 第 5 步：交付

产出两份文件：

1. **诊断报告**：占用排行表 + 每项明细 + 分级清理建议（P0–P3 优先级 + 预计释放量 + 风险）
2. **清理记录与还原指南**：原路径 ↔ 废纸篓名称对照表（用户能自己还原）+ 空间变化表 + 各软件自我恢复行为

## 回答用户高频疑问

**"删了 Homebrew / pip 缓存会不会变慢？"**
不会。删的是下载缓存，不是已装软件。用实测数据回答：
```bash
ls -1 /opt/homebrew/Cellar | wc -l          # 已装 formulae，应完好
/opt/homebrew/bin/brew --version
ls -1 /opt/homebrew/lib/python3*/site-packages | wc -l
```
唯一影响：下次 `brew install` / `pip install` 需重新下载。这正是官方 `brew cleanup` / `pip cache purge` 的常规操作。

**"重装 App 后数据还在吗？"**
取决于该 App 的数据归属（见第 3 步分级表），不能一概而论。

## 沟通原则

- 先给诊断结论，再给行动建议
- 用户说"先不要删"时严格只读扫描，一步都不动
- 每批清理后汇报：删了什么（具体路径+体积）、**刻意跳过什么（及原因）**、空间实际变化
- 刻意跳过高风险项并说明原因，比闷头删完更有价值

