
“C盘红了”可能是Windows用户最不想见到的提示。距离我上次重装系统不到一年C盘可用空间又掉到了3GBD盘明明空着500多GB系统却把所有“重量级”文件堆在系统盘里。后来我写了这套windows系统盘瘦身脚本才把“清理”从临时翻找工具的被动局面变成了一套可重复执行的逻辑。这篇文章就把我的脚本设计、踩坑记录和长期养护思路完整拆给你适合那些不想重装系统、又希望C盘长期保持喘口气余地的朋友。1. 系统盘空间消失的“会计账”先搞清楚瘦身对象1.1 C盘里的空间到底被谁吃掉了很多人一看到C盘变红就直接打开清理软件扫垃圾扫了半天只清出1-2GB觉得问题不大结果过两天又红了。真正的空间消耗大户往往不是浏览器缓存也不是回收站而是系统自己留下来的那些“看不见的膨胀”。拿我实际遇到过的一台机器举例C盘总容量256GB系统加软件占掉90GB剩余空间常年只有十几个GB。用_tree size_一类的工具扫完才看清C:\Windows目录占了60多GB其中WinSxS组件库占到15GBDriverStore驱动仓库占掉9GBSoftwareDistribution\Download更新缓存有5GB休眠文件hiberfil.sys将近12GB页面文件pagefile.sys约16GB再加上Windows.old升级残留20GB。这些项目加一起已经超过C盘一半的容量。关键是这些文件都有一个共同特点它们不会出现在右键“磁盘清理”的默认列表里。磁盘清理工具更多面向临时文件、缩略图缓存、回收站这类“低风险垃圾”对WinSxS、DriverStore、休眠文件这些真正的容量黑洞要么不处理要么得一步步点进深层命令才能操作。手动去搞效率极低还容易漏掉某个大块头。1.2 手动清理为什么不够脚本化为什么更靠谱手动清理最大的问题不是懒而是不可重复、不可审计。今天想起来了清一次下次忘了又是一个月清的时候忘了记录释放了多少空间根本无法判断哪一步真正有效。脚本化的思路是把所有安全清理逻辑写死临时文件怎么清、更新缓存怎么清、组件库如何用官方工具压一遍、旧驱动如何筛选和删除、日志如何截断全部固化成一个脚本文件。每次执行前它会记录C盘当前剩余空间清理完再报告释放了多少每一步写入日志如果清完发现某个软件坏了翻日志就能知道清理过程中动了什么。另外脚本还解决了“权限不一致”的问题。手动清理某些系统目录会弹UAC、提示文件占用脚本以管理员身份运行时很多坑可以直接绕过遇到占用的文件也能用容错逻辑跳过不会像手点删除一样动不动就卡住。1.3 脚本能做什么不能做什么需要先给这套脚本画个边界避免期望过高。能做的清空临时文件、清空Windows更新下载缓存、清理错误报告和转储文件、清空回收站、用系统官方组件清理命令压缩WinSxS、筛选并删除过旧的驱动包、截断应用/系统/安全日志、按需关闭休眠文件、报告释放结果。不能做的不能替代重装来解决底层系统损坏不能把安装在C盘的软件自动“搬迁”到D盘不能阻止未来的软件继续往C盘写东西。脚本只是把“存量垃圾”和“可压缩的系统组件”处理掉至于“增量控制”得靠长线策略我放到最后一部分讲。2. 动手之前先划安全红线2.1 一张表看清哪些能删、哪些别碰写清理脚本最忌讳的是一路Remove-Item -Recurse -Force往下删。我一开始也这么干过后来把一台测试机的驱动仓库清了一半导致无线网卡怎么都驱动不起来所有设备的驱动都被系统重新扫描了一遍才恢复。从那以后我的每个清理脚本都会先定义“安全边界”。下面这张表是我自己反复调整后的清理等级清单目录/文件处理方式风险等级一句话说明C:\Users\用户名\AppData\Local\Temp删除内部全部文件低部分被占用文件跳过即可C:\Windows\Temp删除内部全部文件低需要管理员权限C:\Windows\SoftwareDistribution\Download停服务后清空低-中先停Windows更新服务之后会自动重建回收站清空低确认不需要恢复再操作C:\Windows\Prefetch不建议动低收益压缩启动文件清了反而影响开机预读C:\Windows\Minidump删除低蓝屏转储文件平时没人看C:\Windows\LiveKernelReports删除低内核错误报告Windows错误报告WER目录删除低系统和应用错误日志C:\Windows\Installer不要动高里面是MSI安装和补丁缓存删了软件卸载修复会失败C:\Windows\WinSxS不要直接删高组件存储只能通过Dism在线清理C:\Windows\System32\DriverStore\FileRepository不要整个删中-高只筛选旧版驱动包保留正在使用的驱动hiberfil.sys、pagefile.sys用系统命令调整中不能直接删用powecfg或系统设置迁移C:\Windows\SoftwareDistribution不要整个删中只清Download子目录另外别动DataStore2.2 那些最容易误删的高危区域先重点说说C:\Windows\Installer。这个目录是MSI安装包的系统级备份Office、SQL Server、各种企业软件在安装时会把安装源文件放一份在这里卸载和修复时都要靠它。我见过有人号称清理C盘把这个目录整个打包到了D盘做“瘦身”结果Office从此无法安装更新卸载程序也报找不到源文件。真正要动它只能使用微软官方的MSI清理工具并且强烈建议保留原始文件备份。再看C:\Windows\System32\DriverStore\FileRepository。这是整个Windows里最容易让人误判的路径之一因为从名字看它就是个“驱动菜单仓库”。很多清理教程让用户直接删除这个目录这是极其危险的。DriverStore是Windows驱动包的本地仓库系统在即插即用设备时会从这里查找并加载驱动文件打印机、显卡、声卡、无线网卡、摄像头只要硬件重新扫描就可能回来调用这里的文件。整个删掉轻则设备管理器全是感叹号重则系统在下次开机蓝屏。正确的做法是用pnputil /enum-drivers列出所有第三方驱动找到那些“发布名称”为oemXX.inf、且“驱动程序版本”不是当前设备正在使用的旧版本再单独删除对应的oem包。这个操作必须人工审核不能自动化批量删除我会在第3部分给出可执行命令。2.3 脚本里的白名单与黑名单机制因为安全边界已经很清楚我写脚本时直接内置了两份清单。白名单是可以放心递归删除的路径比如Temp、WER、Minidump黑名单是即使被误扫描到也禁止删除的路径比如C:\Windows\Installer、C:\Windows\System32、C:\Windows\WinSxS、用户文档目录。实际实现并不复杂。在PowerShell脚本开头定义$whitelist ( $env:TEMP, C:\Windows\Temp, C:\Windows\SoftwareDistribution\Download, C:\Windows\Minidump, C:\ProgramData\Microsoft\Windows\WER ) $blacklist ( C:\Windows\System32, C:\Windows\Installer, C:\Windows\WinSxS, C:\Windows\System32\DriverStore )每次删除前都检查目标路径不是黑名单的前缀从源头杜绝误删。3. PowerShell瘦身脚本落地一段一段拆给你看3.1 运行前提与权限自检这个脚本的第一个设计要求是必须以管理员身份运行。因为清空C:\Windows\Temp、清理更新缓存、操作WinSxS组件库都需要系统权限普通模式下运行会大量报错。我在脚本开头放了一段权限自检不是管理员就直接退出# 记录清理前C盘剩余空间 $freeBefore (Get-PSDrive C).Free # 检查管理员权限 $currentPrincipal New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent() ) if (-not $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Host 请以管理员身份重新运行 PowerShell再执行本脚本 -ForegroundColor Red exit } Write-Host 清理前C盘可用空间: $([math]::Round($freeBefore / 1GB, 2)) GB -ForegroundColor Cyan很多朋友问为什么不在脚本里自动加UAC权限请求而是直接退出。原因是PowerShell脚本自身没有“一键提权”的能力提权需要另一个包装脚本或快捷方式反而让整个工具链变得复杂。最稳的方式是用管理员身份打开PowerShell再运行脚本文件简单直接。3.2 清空临时文件最没有技术含量却最有效的第一步临时文件看起来单个文件不大但积少成多。用户目录和Windows临时目录里经常躺着几万个残留文件清理出来往往是数GB级别。$tempFolders ( $env:TEMP, C:\Windows\Temp ) foreach ($folder in $tempFolders) { if (Test-Path $folder) { Get-ChildItem -Path $folder -Force -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue } }这里用-ErrorAction SilentlyContinue是故意的因为Temp目录里总有几个文件被正在运行的进程占用比如Chrome的临时文件、杀毒软件的扫描缓存。这些删不掉的先跳过不影响整体效果。还有一个我很少清的是C:\Windows\Prefetch。网上很多清理教程都会建议清Prefetch但我实测下来它通常只占几十MB而且Windows启动时会在后台重建这些预读文件清完的开机速度甚至会短暂变慢。收益太小不值得写进脚本。3.3 清空Windows更新下载缓存先停服务再动手C:\Windows\SoftwareDistribution\Download里存的是Windows Update下载的补丁安装包。补丁装完以后这些缓存并不会自动清空时间一长就是好几个GB。清理前必须停止Windows Update服务和后台智能传输服务否则文件被占用删不干净还可能边删边写入try { Stop-Service -Name wuauserv -Force -ErrorAction Stop Stop-Service -Name bits -Force -ErrorAction Stop Remove-Item -Path C:\Windows\SoftwareDistribution\Download\* -Recurse -Force -ErrorAction SilentlyContinue Write-Host Windows更新缓存已清理 -ForegroundColor Yellow } finally { Start-Service -Name wuauserv -ErrorAction SilentlyContinue Start-Service -Name bits -ErrorAction SilentlyContinue }这里有个关键的代码习惯清理更新缓存要放在try块里服务重启放进finally块。这样即使删除循环中途崩溃服务也能被重新启动不会出现“清理完Windows更新服务不是没启动”的尴尬局面。3.4 清理错误报告、转储文件与系统日志Windows平时会默默记录大量错误报告和崩溃转储这些文件对普通用户而言几乎没有价值但对空间的影响不小尤其系统连续出现蓝屏时C:\Windows\Minidump和C:\Windows\LiveKernelReports能堆出几个GB。# 清理Windows用户错误报告 Remove-Item -Path C:\ProgramData\Microsoft\Windows\WER\* -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path $env:LOCALAPPDATA\Microsoft\Windows\WER\* -Recurse -Force -ErrorAction SilentlyContinue # 清理系统转储文件 Remove-Item -Path C:\Windows\Minidump\* -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path C:\Windows\MEMORY.DMP -Force -ErrorAction SilentlyContinue # 清理LiveKernelReports Remove-Item -Path C:\Windows\LiveKernelReports\* -Recurse -Force -ErrorAction SilentlyContinue系统日志的清理要谨慎一些尤其是安全日志。我用wevtutil截断日志时默认只处理Application和SystemSecurity日志单独留给用户判断wevtutil cl Application 2$null wevtutil cl System 2$null # 不建议在脚本里默认清理安全日志如需清理请单独手动执行 # wevtutil cl Security原因很简单安全日志是安全审计的关键数据来源企业环境下清理前必须导出留档。个人电脑虽然风险没那么大但万一要排查问题日志被清掉会相当被动。3.5 组件的“官方瘦身法”Dism和pnputil的正确姿势WinSxS组件库和DriverStore驱动仓库是整个系统盘瘦身里最有肉但也最需要谨慎的两个方向。WinSxS不能直接删要用Dism工具做组件清理。它会分析组件存储删除已取代的旧版本组件并压缩剩余组件文件。执行命令是Dism.exe /Online /Cleanup-Image /StartComponentCleanup如果确实需要压缩得更狠可以加/ResetBase参数Dism.exe /Online /Cleanup-Image /StartComponentCleanup /ResetBase但/ResetBase有个副作用Windows会丢失所有已安装更新的“回退能力”以后再也没法单独卸载已经安装的更新补丁。所以我的脚本默认只跑不带/ResetBase的版本只有明确想省空间时才手动追加。DriverStore的方向我的脚本里只做“列出”和“报告”不自动删。因为自动判断一个驱动是否为“设备当前正在使用”很容易判断错删除后造成的硬件故障排查起来费时费力。脚本会先把所有第三方驱动包枚举出来做事后记录pnputil /enum-drivers C:\ScriptLogs\driver-report.txt如果你想手动清理过旧驱动需要人工查看这一份清单找到明确的旧版驱动再执行pnputil /delete-driver oemXX.inf加/uninstall会连设备上已安装的驱动一起卸载除非你确定这个设备不用了否则不要加。整个DriverStore目录永远不要直接Remove-Item。3.6 回收站、休眠文件与系统盘清理工具组合回收站看起来不起眼但批量删除大文件后回收站里能保留几十GB的东西。脚本里加一句即可Clear-RecycleBin -DriveLetter C -Force -ErrorAction SilentlyContinue休眠文件hiberfil.sys的大小约等于物理内存的40%到100%。如果你的电脑内存是16GB这个文件就可能占用6GB甚至16GB。我通常不直接建议关闭休眠因为很多人的笔记本需要“快速启动”功能依赖它。但如果你的C盘实在紧张可以在脚本里加一个显式开关# 按需执行关闭休眠并删除hiberfil.sys powercfg /h off关闭后Windows的“快速启动”也会失效开机速度会变慢一些需要权衡。我个人的做法是保留休眠文件因为省下的空间和开机体验比我更在意后者。最后把系统的存储感知打开。在“设置-系统-存储”里把“临时文件”清理、回收站自动清理都打开让Windows在空间不足时自动做一些基础清理脚本只在每周执行一次做深度清理两者配合。3.7 输出结果与定时执行脚本最后输出本次释放了多少空间并把日志写到固定目录方便后续排查$freeAfter (Get-PSDrive C).Free $releasedGB [math]::Round(($freeAfter - $freeBefore) / 1GB, 2) Write-Host 清理后C盘可用空间: $([math]::Round($freeAfter / 1GB, 2)) GB -ForegroundColor Green Write-Host 本次共释放: $releasedGB GB -ForegroundColor Green # 记录日志 $logDir C:\ScriptLogs if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null } $(Get-Date) 清理前:$([math]::Round($freeBefore / 1GB, 2))GB 清理后:$([math]::Round($freeAfter / 1GB, 2))GB 释放:$releasedGB GB | Out-File -FilePath $logDir\clean.log -Append -Encoding UTF8这样一个脚本已经能自动完成80%的清理动作。设置成每周自动运行的命令如下schtasks /create /tn SystemDiskCleanup /tr powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\CleanSystemDisk.ps1 /sc weekly /d Sunday /st 03:00 /ru SYSTEM需要说明的是/ru SYSTEM的目的是让任务在系统账户下运行不需要登录也不会弹UAC窗口。但如果脚本里某些操作依赖用户环境变量比如$env:TEMPSYSTEM账户跑出来的路径和普通管理员账户不完全一样。所以我更建议用当前管理员账户创建计划任务不填写密码项勾选“只在用户登录时运行”。这也算是个小经验吧。4. 实测后的意外与修复不亲眼看到不会信4.1 一次真实的清理数据拿我自己那台工作机实测清理前C盘可用空间12.6GB脚本跑完重启后可用空间25.1GB一次释放了12.5GB。其中大头分布是清理项释放空间Windows更新缓存2.8GB用户/系统临时文件1.6GBWinSxS组件清理3.2GB驱动仓库旧版驱动2.4GB错误报告与转储文件0.9GB回收站0.8GB其他日志/缓存0.8GB这只是我这台机器的数据不同机器的差异非常大。如果一台电脑从Windows 7时代一路升级到Windows 11WinSxS和DriverStore可能还能多挤出10GB。4.2 DriverStore清理把打印机驱动“清没了”完整排查链路上面脚本里我刻意不让DriverStore自动删驱动就是因为踩过一个很典型的坑。有一段时间我为了省空间手动把DriverStore里老旧的打印机驱动全部删除了用的是pnputil /delete-driver。结果没两天同事那台网络打印机怎么连都连不上Windows显示“找不到驱动程序”。当时的完整排查过程是这样的查看设备管理器打印机在“其他设备”下面带黄色感叹号。打开设备和打印机打印机状态为“驱动不可用”。运行pnputil /enum-drivers在输出的清单里搜索打印机品牌的关键词发现对应的oem包已经不在了。进一步检查C:\Windows\System32\DriverStore\FileRepository确认相关文件夹已被删除确定是清理动过的手。解决方式从打印机厂商官网重新下载驱动程序安装包重新安装驱动设备恢复正常。这个坑的核心教训是直接删DriverStore里的文件不行pnputil /delete-driver也不适合批量操作。驱动程序应该在设备安装时就被备份好或者删除前用dism /online /export-driver整体导出到D盘留存一份。我的脚本后来增加了驱动报告输出功能但只有在人工确认的前提下才会执行删除动作。4.3 文件被占用导致清理不彻底脚本跑完有时候明明显示清理了2GB但过一会儿C盘可用空间又降了一些。这是因为Windows后台服务和杀毒软件会持续产生临时文件或者清理时某些文件正被占用删不掉。这不是脚本失败而是Windows的工作机制决定的。真正的清理不彻底通常出现在“Temp目录里某个文件被某个进程锁死”。我会用资源监视器排查按WinR输入resmon打开资源监视器。切到“CPU”标签页展开“关联的句柄”。搜索提示失败的文件名。看是哪个进程占用了它结束该进程或卸载对应软件。如果是C:\Windows\SoftwareDistribution\Download里的文件被占用多半是Windows Update服务没停干净。检查一下服务状态必要时用sc stop wuauserv停掉清完后再sc start wuauserv拉起来。4.4 Docker/WSL虚拟磁盘才是开发者的“空间黑洞”如果你是开发者系统盘里最容易忽视的空间大户不是垃圾文件而是C:\Users\用户名\AppData\Local\Docker\wsl目录下的虚拟磁盘文件。Docker Desktop在Windows上运行依赖WSL 2后端默认把数据放在C盘容器、镜像、Volume全堆在这个ext4.vhdx虚拟磁盘里。我见过不少开发者的C盘被它吃掉了30GB以上。我处理这个问题的常见步骤# 1. 先用docker system prune清掉无用的镜像和容器 docker system prune -a -f --volumes # 2. 关闭WSL虚拟机 wsl --shutdown然后压缩虚拟磁盘文件避免空间只增不减。先打开diskpartdiskpart在diskpart里执行select vdisk fileC:\Users\你的用户名\AppData\Local\Docker\wsl\data\ext4.vhdx attach vdisk readonly compact vdisk detach vdisk exit这套操作能回收虚拟磁盘里未使用的空间。但有一个先决条件一定要先备份ext4.vhdx文件或者确认里面没有重要的容器数据因为压缩时如果中断虚拟磁盘损坏的概率不低。4.5 清理后npm、git“无法识别”的提醒热词里有好几个“npm无法识别为cmdlet”“git无法识别为cmdlet”的问题。很多人在手动清理系统盘时动了用户环境变量里的PATH或者清理了Node、Git的安装目录结果一开终端就报错“无法将npm项识别为cmdlet、函数、脚本文件或可运行程序的名称”。如果清理完系统盘后遇到这个问题首先不要怀疑是临时文件被删导致的。检查环境变量echo %PATH%在PowerShell里$env:Path -split ;看Node和Git的安装路径还在不在列表里。如果路径确实丢失重新安装对应版本或者手动在“系统属性-环境变量”里把npm所在的目录通常是C:\Program Files\nodejs和git所在目录通常是C:\Program Files\Git\cmd补回去即可。我的清理脚本明确不碰任何环境变量键值只清临时文件和缓存就是不想制造这种本来可以避免的麻烦。4.6 安全日志越堆越大还有一台服务器安全日志占用达到20多个GB打开事件查看器卡到几乎无法操作。我的脚本默认不清理Security日志但对这种特殊情况手动执行以下命令可以立即释放空间wevtutil cl Security如果担心日志里有告警信息建议先导出wevtutil epl Security D:\backup\security_%date:~0,4%%date:~5,2%%date:~8,2%.evtx导完再清空间立竿见影。不过普通个人电脑的安全日志一般不会太大只有开启了审核策略或安装了安全软件的设备才会疯狂堆积按需处理就好。5. 把系统盘“养瘦”的长线操作5.1 把“大件”迁出C盘脚本能帮你清掉存量垃圾但如果用户目录、Docker、WSL这些“增量大件”都默认往C盘写清得再勤也扛不住。我自己的策略是把所有可迁移的大组件都搬家。WSL发行版的迁移很多人容易忽略。先用wsl --export导出分发版再wsl --import到D盘wsl --export Ubuntu D:\backup\ubuntu-backup.tar wsl --unregister Ubuntu wsl --import Ubuntu D:\WSL\Ubuntu D:\backup\ubuntu-backup.tar注意wsl --import后的根用户不是原发行版的默认账号可能需要重新设置默认用户但磁盘空间的改善是立竿见影的。Docker Desktop可以在设置界面里把Disk image location从C盘改到D盘不过这个操作最好在迁移前先把旧虚拟磁盘备份好否则照样有数据风险。Node的npm缓存、Python的pip缓存也可以迁移npm config set cache D:\Cache\npm pip config set global.cache-dir D:\Cache\pip5.2 存储感知与计划任务组合Windows自带的存储感知现在做得比想象中好建议在“设置-系统-存储-存储感知”里打开“自动清理临时文件”和“自动清空回收站”把频率设成每次空间不足时清理。它负责日常兜底我的脚本负责每周深度清理两者搭配之后C盘的可用空间基本能稳定下来。如果不想用计划任务的命令也可以在“任务计划程序”图形界面里手动创建任务让脚本每周日凌晨运行一次。触发条件选“按计划”每周、周日、凌晨3点。操作里填powershell.exe参数填-ExecutionPolicy Bypass -File C:\Scripts\CleanSystemDisk.ps1并勾选“以最高权限运行”。5.3 找出那些脚本看不见的大文件脚本能清理的是“系统已知的临时和缓存”但有些软件会在系统盘疯狂写数据比如某些国产办公软件、IM软件的本地聊天记录数据库动辄10GB起步。这类文件脚本无法判断是否可删需要靠分析工具辅助。我推荐用WizTree或者TreeSize这类工具扫描速度极快几秒钟就能把整个C盘的文件夹大小按从大到小排出来。每周跑完清理脚本后用它们看一眼哪个目录突然膨胀就立刻能发现。看着那些几十GB的目录比自己瞎猜要靠谱得多。5.4 最后分享一点个人体会写了这么多脚本、踩了这么多坑之后我最想告诉你的一点是系统盘瘦身的核心不是“删得多”而是“可预期”。清理每一步都会输出日志每次都知道动过哪里、释放了多少、如果出问题能从日志里定位原因这比任何一键式的“清理大师”都让人放心。我自己的电脑现在C盘长期保持30%至40%的剩余空间靠的不是重装也不是第三方工具而是这套可以反复执行的脚本加每个月瞄一眼大文件目录的习惯。如果你也想省心建议先跑一遍脚本看看效果再按自己的使用习惯把长线策略逐步落实。