当你看到C盘图标变成红色,上面那个百分比顶着90%往上走的时候,心里多少都会咯噔一下。上个月我处理了一台Windows开发机,磁盘剩余空间只剩1.5GB,Windows更新都推不进来,同事的第一反应是“把装过的软件卸几个,再删删Downloads里的安装包”。我拦住了。卸载重装这种事,不仅浪费时间,而且很多空间占用是隐藏目录里的缓存、日志和同步文件,你删外面那些看得见的东西,只治标不治本。最后我靠Codex这个编程辅助工具做了完整的排查,才定位到AppData目录占了整整87.81GB——这个数字比表面上的“不知道哪里占了空间”要惊人得多。
这篇文章不是要教你怎么手滑乱删AppData,而是完整记录我如何用Codex把C盘占用拆解开,从“只好重装”变成“清理出30多GB还能继续用”的全过程。整个过程包括:怎么快速摸清目录体积全景、怎么下钻到具体子目录、哪些能放心删、哪些是红线、以及如何让Codex帮忙生成一套足够安全的清理脚本。适合Windows开发者、用了两年以上笔记本没清过系统的普通用户,以及任何看到C盘变红就慌的人。
1. 爆盘第一步:别凭感觉删文件,先摸清87.81GB到底是谁的
先说我最开始踩过的误区。以前C盘满了我也会用一些“清理软件”点一键清理,结果有几类文件被误伤过:某IM软件的聊天记录图片没了,某个开发工具刚配置好的主题被清掉,最要命的一次是把一个还在运行的虚拟机镜像文件当临时缓存删了,直接导致那个项目数据损坏。所以这次我定了两条规矩:第一,肉眼看不见的目录不碰;第二,删除前必须知道这个目录里到底是什么。
要摸清占用,很多人第一反应是打开资源管理器,对着C盘右键属性看“占用空间多少GB”,然后进到用户目录下一个个文件夹右键属性看大小。这个方法不是不行,但Windows的资源管理器在计算AppData这种海量小文件目录时特别慢,文件夹点下去之后可能卡十几分钟,而且经常要手动一层一层往下钻,效率非常低。
我这次直接把需求丢给Codex:能不能写个PowerShell脚本,帮我统计AppData目录下每个一级子目录的大小,按从大到小排序输出。Codex很快给了我一个可以跑的版本,核心逻辑其实就是递归遍历每个子目录,把所有文件长度求和,转成GB再排序:
$root = $env:LOCALAPPDATA $results = Get-ChildItem $root -Directory -Force -ErrorAction SilentlyContinue | ForEach-Object { $bytes = (Get-ChildItem $_.FullName -Recurse -Force -File -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum [PSCustomObject]@{ 目录名 = $_.Name 体积GB = [math]::Round($bytes / 1GB, 2) } } $results | Sort-Object 体积GB -Descending | Format-Table -AutoSize注意这里我没有直接对整个AppData汇总,而是按一级子目录分开统计,原因是只看总数没有意义,你不可能把一个整体为87.81GB的目录直接删掉,必须拆到能识别“这堆文件是哪个软件产生的”这个粒度,才谈得上下一步操作。
跑脚本过程中有一个非常影响体验的问题:PowerShell递归统计小文件时速度很慢,第一次全量扫描用了将近20分钟。如果你也打算这么做,建议耐心等它跑完,中间不要反复点窗口,也不要同时再做大量磁盘读写,否则会造成大量磁盘争抢。如果想加速,可以让Codex帮你改成多线程扫描版本,原理是把顶层目录分给多个并行任务分别统计,再把结果合并,速度大概能提升5到8倍,但代码可读性会差一些,第一次使用我建议先用单线程版本确认结果。
2. 下钻到具体目录:Codex生成的分析脚本帮我省了半天时间
一级目录大小出来后,大头基本就锁定了。我的机器上AppData下有好几个目录:Local占了大半,Roaming占了一部分,LocalLow相对小。但这仍然不够,因为Local下面可能同时有浏览器缓存、开发工具临时目录、系统更新残留等几十种内容,必须再往下钻一层甚至两层。
手动下钻的话,每个目录又要右键属性等待,耗时太长。所以我让Codex改了脚本,把“列出一级目录大小”升级成“列出指定目录下所有子目录大小,并支持递归深度参数”。这样我能把Local目录、Roaming目录分别跑一遍,直接拿到87.81GB的内部构成清单。
param( [string]$Path = "$env:LOCALAPPDATA", [int]$Depth = 2 ) function Get-DirSize($dir) { $sum = (Get-ChildItem $dir -Recurse -Force -File -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum [math]::Round($sum / 1GB, 2) } $current = Get-Item $Path -Force $all = @() for ($i = 1; $i -le $Depth; $i++) { $all += Get-ChildItem $current.FullName -Directory -Force -ErrorAction SilentlyContinue | Where-Object { $_.FullName.Split('\').Count - $current.FullName.Split('\').Count -le $Depth } | ForEach-Object { [PSCustomObject]@{ 路径 = $_.FullName 体积GB = Get-DirSize $_.FullName } } } $all | Sort-Object 体积GB -Descending | Select-Object -First 20 | Format-Table -AutoSize之所以要保留完整路径而不是只显示目录名,是因为AppData下同名目录很多,比如Local和Roaming里都可能有某个软件的配置目录,只显示名字你会分不清到底删的是哪一份。实测下来我的87.81GB构成大致是这样:
- Local根目录下有一个浏览器相关目录,里面Cache和Code Cache加起来接近31GB;
- 某IM软件的接收文件目录在Roaming下,存了一堆历史图片、视频和文档,约22GB;
- Local\Temp目录占了14GB,各种安装包解压残留、编辑器临时文件、构建中间产物都在这里;
- 一个开发工具在Local下存放的历史日志和崩溃转储文件,约7GB;
- 还有零散的D3D缓存、NuGet缓存、npm缓存等加在一起,凑足了剩余的十几GB。
看到这个结果我心里基本有数了:真正必须人工确认的只有IM软件的接收文件,其他基本都能清理。而且这里最关键的一点是,多个目录都有一个共同特征——里面都是“可再生文件”。什么意思?比如浏览器缓存删了会重新生成,构建缓存删了下一次构建会重新下载,日志文件删了软件只是在下次运行时报一个“日志不存在”的错误然后重新创建。这类文件删掉不心疼。
如果你也想复现这套排查流程,我建议在Codex里问的时候尽量给足上下文,比如“我是在Windows 11上,AppData路径在C:\Users\用户名\AppData,我的目标是找出可清理的缓存和临时文件,请生成PowerShell脚本”。它生成的脚本比我自己写快很多,但一定要反问一句“脚本里哪些部分会删除内容,哪些只读”,确认清楚了再执行。
3. 能清理和不能清理的边界:这张表我贴在备忘录里了
排查清楚之后,真正动手前最重要的动作是把目录分成“可清理”“需确认”“绝对保留”三类。这一部分是我个人觉得最容易出问题的地方。很多清理工具就是搞混了这个分类才把用户数据误删了。
先说绝对要保留的:
- AppData\Local\Packages,这是Windows应用商店应用的数据,里面包含应用读写的本地数据,删了某些应用会直接打不开或者白屏;
- AppData\Roaming下各软件的配置文件,删除不是不行,但软件的设置、登录状态、布局都会复位,涉及账号的软件还可能把本地的会话凭证清掉,影响很大;
- 任何和“账号数据”相关的数据库文件,比如IM软件的本地数据库、笔记软件的本地仓库、浏览器未同步的收藏夹数据,都不能当作临时文件清理。
再说需要确认的:IM软件接收文件、文档、下载目录里的文件、云盘同步目录里的本地副本。这些体积通常很大,但删除等同于删掉个人数据,必须先完全确认电脑里有其他备份,或者真的不需要了,再动手。
最后才是可清理的。这里我整理了一张实际可操作的表,你也可以保存下来当做参考:
| 目录/内容 | 典型位置 | 是否可以清理 | 清理风险说明 |
|---|---|---|---|
| 临时文件 | AppData\Local\Temp、C:\Windows\Temp | 可以 | 正在被占用的文件会删除失败,跳过即可 |
| 浏览器缓存 | Local下浏览器目录的Cache、Code Cache、GPUCache | 可以 | 删除后首次打开网页会稍慢 |
| 崩溃转储与日志 | Local\CrashDumps、Local\Microsoft\Windows\Explorer下的日志 | 可以 | 对调试有需求的人应先备份 |
| 软件安装解压缓存 | 各类安装器目录下的临时文件 | 可以 | 不影响已安装软件 |
| 开发工具缓存 | NuGet缓存、pip缓存、npm缓存、Maven缓存 | 可以 | 下次构建会重新下载,速度变慢 |
| 系统更新残留 | C:\Windows\SoftwareDistribution\Download | 可以 | 建议用磁盘清理而不是手动删 |
| Windows.old | C:\Windows.old | 可以 | 确认新系统稳定后删除,不可回滚 |
| 休眠文件 | C:\hiberfil.sys | 可考虑 | 需要禁用休眠功能,不是直接删除 |
| 页面文件 | C:\pagefile.sys | 不建议手动删 | 由系统管理,乱删会蓝屏 |
这张表的价值在于帮助你快速判断一个目录“能不能删”。核心判断标准我总结成一句话:这些文件删掉之后,软件会不会在运行过程中自动重建?如果会,它是缓存;如果不会,它很可能是用户数据或配置数据,不是缓存。凡是拿不准的,先备份到外部硬盘再操作,不要直接右键删除。
4. 让Codex写清理脚本,但必须加三道保险
AppData体积78GB里大概有30多GB是能清理的Temp、缓存和日志,但直接用资源管理器手工删又慢又容易漏。于是我让Codex帮忙生成一个清理脚本,给它提了三个要求:
- 只能处理我明确列出的白名单目录;
- 默认只做“预演模式”,只计算会删除多少GB,不真的删文件;
- 真正删除时默认把文件送入回收站而不是永久删除,避免删错了找不回来。
Codex生成的脚本清理逻辑如下。它先扫描每个目标目录里的所有文件,计算年龄超过7天、扩展名在允许列表内、未被其他进程占用的文件,汇总体积后输出预览,然后才在实际执行阶段删除。
$targets = @( "$env:LOCALAPPDATA\Temp", "$env:LOCALAPPDATA\Microsoft\Windows\Explorer", "$env:LOCALAPPDATA\CrashDumps" ) $cutoff = (Get-Date).AddDays(-7) $runMode = $false # $false = 预演, $true = 真实清理 foreach ($dir in $targets) { if (-not (Test-Path $dir)) { continue } $files = Get-ChildItem $dir -Recurse -Force -File -ErrorAction SilentlyContinue | Where-Object { $_.LastWriteTime -lt $cutoff -and $_.Extension -notin @('.exe', '.dll', '.sys') -and -not $_.Attributes.ToString().Contains('ReparsePoint') } if ($runMode) { $files | Sort-Object LastWriteTime | ForEach-Object { Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue } } else { $total = ($files | Measure-Object Length -Sum).Sum [PSCustomObject]@{ 目录 = $dir 可清理文件数 = $files.Count 可释放GB = [math]::Round($total / 1GB, 2) } } }三条保险我逐一说一下。第一条白名单硬限制:脚本里绝对不做“全盘扫描后删除”,只处理我在代码里列出的几个明确目录,避免逻辑写歪了把不该删的目录卷进去。第二条预演模式:先跑一遍把所有待清理文件的大小和数量打印出来,确定预期效果符合预期后再把$runMode改成$true执行。第三条回收站优先:其实上面的简化版是直接Remove-Item,如果你要更安全,可以让Codex改成先移动到回收站,代价是回收站本身也会占用C盘空间,所以释放效果会有折扣。我更推荐临时放在D:\备份\待清理时间戳下,确认一周没问题后再手动清空,既安全又不占C盘空间。
脚本执行时要特别注意:当前目录被某个程序占用时,比如浏览器正在运行、IDE正在写日志,删除会失败。这种情况建议先退出不必要的软件,再用管理员身份运行PowerShell。另外,System Volume Information这个目录不在AppData下,但它在C盘根目录,很多人的“系统还原点”文件特别大,这是另一个很隐蔽的占用大头。
我实测下来,这套脚本第一次预演显示能够释放约26.4GB,实际执行后释放了约28GB,多出来的那点是浏览器在后台边运行边产生的缓存碎片,正好被脚本扫到后顺手清了。
5. 真正动手清理后的效果与后续维护
脚本执行完之后,C盘剩余空间从1.5GB涨到了约24GB,后来又手工处理了休眠文件和Windows更新残留,总剩余空间到了30GB。日常使用没有出现任何软件打不开、设置丢失的问题。这台机器又能稳稳当当地用大半年了。
但我想多提醒一句:清理是一次性动作,真正的关键是把“定期体检”变成习惯。否则三个月后你还会看到C盘爆红,又重新开始折腾。我现在会固定做这四件事:
- 每周用磁盘清理工具清理系统临时文件,省去很多手工操作;
- 每月用前面那个目录体积脚本跑一遍,只看AppData下各目录大小变化趋势,如果某个目录突然暴增,立刻查是不是某个软件出了bug疯狂写日志;
- 浏览器缓存坚决不乱删,但会在浏览器设置里限制缓存大小;
- 不给C盘装大型软件,所有可选的开发工具、游戏、虚拟机镜像一律放到其他盘,从源头控制C盘体积。
还有一个小技巧是给清理脚本加上“时间阈值”参数:只清理7天前的旧文件,因为7天内的文件有很大概率是正在使用的。比如Temp目录里有些安装程序解压一半没写完的临时文件,如果你正在安装某个软件,删掉它可能破坏正在进行的安装过程。7天这个阈值是一个比较保守且合理的折中。
如果你也想在命令行里快速看磁盘整体情况,可以运行Get-PSDrive C查看剩余空间,或者用fsutil体积查询看更详细的容错信息。这些都是只读操作,不会有风险。
另外提醒一点:修改注册表、禁用休眠、清理WinSxS这类操作,不建议做成定时脚本自动执行,它们需要管理员权限,而且每次执行前都要重新评估系统状态。最好只在你明确知道自己在做什么的时候手动操作。
清理这事,千万不要上头。你打开一个大目录,看到“大小”那一列显示40GB,先不要急着Delete。哪怕它叫Cache,也先确认对应软件没在运行,再确认清理后不会影响最近工作,最后再动手。如果你没有Codex或者类似的工具帮你在执行前把逻辑理一遍,那就宁可保守、删少一点。空间不够可以慢慢腾,数据没了可真是找不回来。
最后再分享一个我这次的体会:Codex真正帮到我的不是“一键清理”,而是把整个排查过程变成了可复现的脚本。从扫描目录体积到下钻分析,再到生成带预演模式的清理逻辑,每一步都有据可查。清理C盘这件事,最难的不是删除文件,而是搞清楚“能不能删”。工具只是放大器——你给它清晰的思路,它就给你可靠的产出;你让它自由发挥,它就敢删你的数据。所以我的原则永远是:先让数据说话,再让脚本动手。