C盘又飘红了,磁盘空间不足的弹窗跳出来的时候,大多数人第一反应是打开各种清理软件点一遍“一键清理”。但用过的人都知道,这玩意清完没多久空间又回去了,而且动不动夹带私货,动不动就要你开会员。我自己是写脚本的人,从接触bat到后来用PowerShell,折腾过不少清理方案,今天就把这套本地电脑C盘清理脚本从头到尾拆一遍,包含清理目录的边界、脚本怎么写、为什么有的脚本一运行就闪退、怎么挂到任务计划里让它自己干活。无论你是普通用户还是写代码的,照着抄作业就行。
1. C盘为什么总是爆满:先搞清楚垃圾到底堆在哪里
1.1 最常见的三类C盘“吞金兽”
C盘空间不是一夜之间没的。你回忆一下,系统盘空间通常是被三类东西吃掉:第一类是系统和软件的临时文件,说白了就是程序跑的时候生成的中间产物,很多程序退出之后并不会主动清理,日积月累就是几个G甚至十几个G;第二类是缓存文件,浏览器缓存、缩略图缓存、软件更新缓存,这类文件设计出来的本意是加速下次访问,但如果长期没人管,就会膨胀到非常离谱的体量;第三类是日志和旧版本文件,Windows系统更新会留下备份,系统事件日志一直在写,软件卸载之后也会残留一堆配置和数据,这些都属于“看起来不占地方,实际加起来吓死人”的部分。
我见过最夸张的一台机器,C盘500G用了490多G,排查下来Windows更新缓存占了80多G,浏览器缓存占了几十个G,光是这两个大头清完就释放了接近一半空间。所以你看,清理的前提是先定位,知道垃圾集中在哪里,脚本才有意义。
1.2 为什么手动清理和垃圾清理软件经常不管用
手动清理的问题在于不明所以。大多数人只知道清回收站,清下载文件夹,但这些根本动不了上面说的几块大骨头。Windows自带的磁盘清理是一个入口,但它默认不会打开所有清理项,而且它对很多第三方软件缓存毫无办法。至于第三方清理软件,问题更大,一个是弹窗广告和推广捆绑,另一个是它们为了让你继续买会员,通常会留一手,真正能清出来的空间永远不可能让你满意。
更深一层的原因,很多用户懒得去搞懂哪些目录能删哪些不能删,干脆全部交给工具,但工具本身的规则是黑盒的。我的观点是,清理这件事一定要掌握在自己手里,你不需要一次性搞清楚Windows所有目录的用途,只要能守住几条安全边界,写一个脚本把那些明确无害的文件清掉,效果就比大多数一键清理工具好得多。这也是我为什么一直坚持用脚本的原因:项目是自己写的,每一步干什么清清楚楚,不会误删,不会被套路。
2. 清理脚本的核心边界:什么能删、什么不能删
写清理脚本,第一原则不是“清得多”,而是“删不错”。我见过有人图省事,直接对整个 C 盘跑递归删除,结果系统崩了只能重装。所以脚本里每一条目录路径,都必须有明确的依据。下面我把清理清单和禁区完整摆出来,照着抄可以,但前提是你得理解为什么。
2.1 可安全删除的目录清单
先说能删的,我把它们分成几个级别,按安全性从高到低排:
| 清理项 | 路径 | 说明 | 风险等级 |
|---|---|---|---|
| 用户临时目录 | %TEMP%、%LOCALAPPDATA%\Temp | 程序运行时生成的临时文件 | 低 |
| 系统临时目录 | C:\Windows\Temp | 系统组件、安装程序产生的临时文件 | 低 |
| Windows更新缓存 | C:\Windows\SoftwareDistribution\Download | 更新的安装包缓存,安装完成后无用 | 低(需停服务) |
| 回收站 | C:\$Recycle.Bin | 通过Clear-RecycleBin命令清空 | 低 |
| 缩略图缓存 | %LOCALAPPDATA%\Microsoft\Windows\Explorer | 图片缩略图缓存,自动重建 | 低 |
| 软件日志 | C:\Windows\Logs下载目录等 | 系统组件运行日志 | 中 |
| 浏览器缓存 | %LOCALAPPDATA%\Microsoft\Edge\User Data\Default\Cache等 | 浏览器网络缓存 | 中 |
| 分发缓存 (WinSxS) | C:\Windows\WinSxS | 不能直接删文件,用DISM组件清理 | 中 |
这里面最容易被大家忽略的是%LOCALAPPDATA%\Temp。很多人只清C:\Windows\Temp,但当前用户的临时目录往往是最大的垃圾场,编译缓存、软件解压的中间产物、聊天软件图片临时加载文件全在那。我清理过的机器里,光这个目录清出 10G 以上都很常见。
2.2 千万不能碰的目录和文件
红色禁区不用记太多,但要记得死:
C:\Windows\System32和C:\Windows\SysWOW64,这俩是系统核心运行库,删一个文件系统就可能蓝屏。C:\Windows\WinSxS,这个目录很特殊,它只是看起来大,里面是并行组件存储,不能直接手动删文件,要用Dism /Online /Cleanup-Image /StartComponentCleanup去清理旧版本组件。C:\Program Files和C:\Program Files (x86),这是安装软件的位置,不能靠脚本“清理”,卸载软件要走正规卸载程序。C:\Users\你的用户名下的文档、桌面、图片、视频目录,默认不能清理,除非脚本里明确指定了只清某一类缓存子目录。- 页文件
pagefile.sys和休眠文件hiberfil.sys,这俩是系统虚拟内存和休眠镜像,不是垃圾文件,删除会导致系统不稳定,只能通过系统设置调整大小或关闭休眠功能。
2.3 删除前必须养成的备份习惯
哪怕清单再安全,我也建议在正式清理前做一次系统还原点,或者至少把脚本删掉的内容先记到日志里。操作方式很简单:在PowerShell里跑Checkpoint-Computer -Description "Before-Cleanup" -RestorePointType MODIFY_SETTINGS建一个还原点,之后就算手滑删了不该删的,也有后悔药。我实际清理过几百台机器,从没遇到过还原点用上的情况,但心理安全感完全不一样,强烈建议保留这层保险。
3. 从零写一个C盘清理脚本:环境准备与脚本主体
3.1 清理脚本的选型:批处理还是PowerShell
很多人在群里面问清理脚本怎么写,我看到的大量答案是放一段.bat批处理。bat 确实简单,几行del命令就能跑,但它有几个绕不开的痛点:中文路径容易乱码,删除大量文件时没有进度反馈,出错处理很弱。所以我自己的主力方案是 PowerShell 脚本,.ps1格式。
PowerShell 优势很明显:
- 原生支持中文,不存在编码问题;
- 有
Remove-Item -ErrorAction SilentlyContinue这种细粒度的错误控制; - 可以直接调用 .NET 类库,比如算目录大小、处理文件占用;
- 能配合 Windows 任务计划程序做高级调度。
当然最后我会补一个 bat 版本,给那些不想碰 PowerShell 执行策略的老哥应急用。但如果条件允许,真心建议用 ps1。
3.2 可用脚本逐段拆解
下面这个脚本是我自己日常在用的精简版,先放完整代码,再逐段解释。
# C盘清理脚本 Clean-CDrive.ps1 # 运行前建议以管理员身份打开 PowerShell $logPath = "C:\CleanupLogs\clean_$(Get-Date -Format 'yyyyMMdd_HHmmss').log" New-Item -ItemType Directory -Path (Split-Path $logPath) -Force | Out-Null function Write-Log { param([string]$Message) $ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss" Write-Host "$ts $Message" Add-Content -Path $logPath -Value "$ts $Message" } # 1. 清理用户临时目录和系统临时目录 $tempPaths = @( "$env:TEMP", "$env:LOCALAPPDATA\Temp", "C:\Windows\Temp" ) foreach ($p in $tempPaths) { if (Test-Path $p) { $before = (Get-ChildItem $p -Recurse -Force -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum Remove-Item "$p\*" -Recurse -Force -ErrorAction SilentlyContinue $after = (Get-ChildItem $p -Recurse -Force -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum $freed = [math]::Round(($before - $after) / 1MB, 2) Write-Log "Cleaned $p, freed ${freed} MB" } } # 2. 清空回收站 Clear-RecycleBin -Force -ErrorAction SilentlyContinue Write-Log "Recycle Bin cleared" # 3. 清理 Windows 更新缓存(先停止 Windows Update 服务) $wuService = Get-Service -Name wuauserv -ErrorAction SilentlyContinue if ($wuService) { Stop-Service -Name wuauserv -Force -ErrorAction SilentlyContinue Remove-Item "C:\Windows\SoftwareDistribution\Download\*" -Recurse -Force -ErrorAction SilentlyContinue Start-Service -Name wuauserv -ErrorAction SilentlyContinue Write-Log "Windows Update cache cleaned" } # 4. 清理缩略图缓存 Remove-Item "$env:LOCALAPPDATA\Microsoft\Windows\Explorer\thumbcache_*.db" -Force -ErrorAction SilentlyContinue Write-Log "Thumbnail cache cleaned" # 5. 清理浏览器缓存(Edge / Chrome,按需取消注释) $browserCachePaths = @( "$env:LOCALAPPDATA\Microsoft\Edge\User Data\Default\Cache", "$env:LOCALAPPDATA\Google\Chrome\User Data\Default\Cache" ) foreach ($p in $browserCachePaths) { if (Test-Path $p) { Remove-Item "$p\*" -Recurse -Force -ErrorAction SilentlyContinue Write-Log "Browser cache cleaned: $p" } } # 6. 使用 DISM 清理 WinSxS 旧组件(耗时较长,可选) # Dism.exe /Online /Cleanup-Image /StartComponentCleanup # Write-Log "WinSxS component cleanup done" Write-Log "Cleanup finished."3.3 核心逻辑说明
这段脚本的核心逻辑分三步:锁定目录、删除内容、记录日志。
第1步$tempPaths是一个数组,里面放了我们要清理的所有临时目录路径。“清理目录”实际含义是删除目录里的所有内容,而不是删除目录本身,所以用的是$p\*,不是$p。这个细节很重要,否则你会发现清理完 Temp 目录自己也消失了。
第2步Remove-Item -Recurse -Force -ErrorAction SilentlyContinue是关键组合。-Recurse表示递归删除子目录和子文件;-Force强制删除隐藏和只读文件;-ErrorAction SilentlyContinue的意思是遇到正在被占用的文件、没有权限的文件时不要报错中断,直接跳过。这个参数对脚本稳定性太重要了,没有它,清理到一半碰到一个被占用的 dll 文件整个脚本就会红屏。
第3步我用了一个Write-Log函数,每次清一个目录就记录清了多少空间、什么时候清的。这个日志习惯是写清理脚本最容易忽略的地方,但实际价值很高——你能清楚地看到每次清理的真实效果,而不是凭感觉说“清完是不是少了几个G”。
另外注意第3段,清理 Windows 更新缓存之前先停掉了wuauserv服务,清完再启动。如果不这么做,下载缓存目录的文件正处于被系统服务锁定的状态,删除会失败,甚至可能导致后续更新异常。我之前第一次写这功能时就没停服务,结果清除失败不说,文件还残留在那里,空间完全没释放。
4. 脚本运行过程中的三大致命坑:闪退、执行策略与文件占用
4.1 Windows脚本命令闪退的排查链路
很多人在网上搜“Windows脚本命令闪退”,搜到了脚本,抄下来双击运行,结果窗口闪了一下就没了,什么都没发生。这个我有话说,闪退的原因 90% 是这三个:
第一个原因是脚本文件编码不对。bat 脚本如果里面有中文,文件保存成了 UTF-8 编码,那么 cmd 默认用系统 ANSI 编码解析,中文全部变乱码,执行到乱码那一行就直接退出了。解决办法是bat文件另存为 ANSI 编码,或者干脆 PowerShell 脚本保存成 UTF-8 with BOM。我在实际写脚本时,纯 bat 就直接全英文注释,不碰中文,这是最省事的。
第二个原因是脚本路径名带了空格。很多人把脚本放在C:\Users\My Documents\C Drive Cleanup\这种带空格的目录里面,双击 bat 或 ps1 运行后,路径被截断,找不到文件,一闪而过。解决办法是运行之前先cd /d切换到脚本所在目录,或者在调用脚本的时候用引号把完整路径包起来。
第三个原因是执行策略限制。PowerShell 默认情况下禁止运行未签名的本地脚本,双击 ps1 文件时系统只会在记事本里打开它而不是执行。这个时候就算不闪退,你也跑不起来。
4.2 PowerShell执行策略与“无法加载文件”问题
在 PowerShell 里面执行脚本时,如果系统提示 “无法加载文件 ...,因为在此系统上禁止运行脚本”,那你遇到的就是执行策略问题。这个问题在热搜词里面反复出现,原因很简单:Windows 默认的Restricted策略基本不允许跑本地 ps1 脚本。
解决方式有两种:
# 查看当前执行策略 Get-ExecutionPolicy -List # 当前用户设置成 RemoteSigned,允许本地未签名脚本运行 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUserRemoteSigned的意思是:本地创建的脚本可以运行,从互联网下载的脚本必须带可信签名才能运行。日常调试清理脚本,RemoteSigned是最合适的配置,不要图省事直接设成Unrestricted,没必要给自己挖坑。
如果你是以管理员身份运行 PowerShell,还可以用组策略的方式去开,但个人电脑直接用命令行设置就行,一劳永逸。
4.3 文件占用导致的删除失败
脚本运行一段时间后,你会发现日志里面某些目录释放的空间是 0 MB。别慌,这大概率不是脚本写错了,而是文件被占用。关于占用,主要有两个来源:一是杀毒软件正在扫描这些临时文件,二是某个应用程序正在写缓存。处理办法是给Remove-Item加上-ErrorAction SilentlyContinue,跳过这些文件,不要中断整个脚本。
另外一个技巧是清理浏览器缓存前先退出浏览器。如果你在脚本运行的时候浏览器开着,Cache 目录下的文件基本都会锁定,全部删不掉。我写的脚本里不会强制关闭浏览器,因为太霸道了,所以我通常在脚本开头加一个提醒:
Write-Host "请先关闭浏览器再运行清理脚本,否则缓存清理不完整。" -ForegroundColor Yellow这种提醒对用户体验很重要,运行之前就知道该怎么做,而不是跑了半天才发现啥也没清掉。
5. 让清理变成日常:任务计划程序与开机自启的折腾经验
5.1 用任务计划程序做自动清理
清理脚本最大的价值在于定时执行,而不是每次手痒了才跑一次。Windows 自带的“任务计划程序”就能搞定,不依赖任何第三方工具。
操作步骤并不复杂:
- 按
Win + R,输入taskschd.msc,打开任务计划程序; - 右侧点击“创建基本任务”;
- 名称填 “C盘自动清理”,触发器选“每天”,时间你可以选凌晨或者午休时间,我一般是凌晨2点,那时候基本不会有人用电脑;
- 操作选“启动程序”,程序填
powershell.exe,参数填-NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\Clean-CDrive.ps1"; - 完了之后,双击这个任务,在“常规”选项卡勾选“使用最高权限运行”,确保脚本以管理员权限执行。
这里有个小坑:如果任务计划里调用的 ps1 路径含有空格,参数里必须加上引号,否则系统找不到文件。我见过太多人在这一步翻车,任务计划一直报错找不到文件,其实就把路径加上英文双引号就行。
另外,触发器设置成“每天”不是死板的,你可以切成“每周”或“登录时”,看你自己使用习惯。如果你电脑每天固定时间开机,选每天没问题;如果电脑不是天天开,建议选“启动时”或者“登录时”,否则一周过去一次都没跑过。
5.2 开机自启脚本的配置门槛
有些人不想用任务计划,就想让脚本开机直接跑。思路也不难,把 ps1 的快捷方式放到开机启动目录shell:startup即可,或者注册一个 Run 注册表项。但我实际用下来,强烈不建议用开机自启方式运行清理脚本。
原因是开机瞬间系统和各种软件都在初始化,文件锁定非常严重,临时目录里可能有大量的文件正在被写。这时候你跑清理脚本,大部分文件删不动,效率极低,而且还有可能误伤启动中的软件所需的临时文件,导致软件启动出错。任务计划的好处是触发时机可控,你完全可以设定在开机后10分钟执行,那时候系统和常用软件已经稳定下来了。
如果想在 PowerShell 脚本里做“延迟启动”,可以直接写:
Start-Sleep -Seconds 60放在脚本开头,等待一分钟再开始清理,简单粗暴但也有效。
5.3 日志分析与清理效果验证
脚本跑完不能白跑,你得看日志。我写的脚本会把每次清理的时间和释放空间写到C:\CleanupLogs目录下,文件名带时间戳。看日志的意思不是只瞄一眼“嗯跑完了”,而是对比几次清理的数据。
举个实例来说明,我第一次帮同事清理他的工作笔记本,跑了脚本,日志显示临时目录释放了 3.2GB,Windows更新缓存释放了 5.8GB,回收站释放了 1.1GB,加起来大概 10GB 左右。表面上看效果很好,但这说明这台电脑已经很久没清理过了。等到第二次清理,日志显示释放空间只有 300MB,这个时候就说明系统进入正常节奏了。如果哪一天日志数据突然又飙到好几个G,那大概率是某个软件出了问题,疯狂写缓存,那就不只是清理的问题了,得排查软件本身。
6. 清理脚本的进阶玩法:空间统计、多级策略与扩展方向
6.1 用脚本统计大文件并给出清理建议
基础清理脚本能解决80%的C盘空间问题,但剩下的20%往往是大文件占据的。比如微信和QQ的聊天记录、开发工具缓存的虚拟设备文件、Docker镜像那些大家伙,脚本不能盲目清理,但它可以帮你找出来。
在 PowerShell 里统计文件夹大小是很成熟的操作,我一般会用这样的函数:
function Get-FolderSize { param([string]$Path) $size = (Get-ChildItem $Path -Recurse -Force -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum return [math]::Round($size / 1GB, 2) } Get-FolderSize "C:\Users\$env:USERNAME\AppData\Documents\WeChat Files"把常见大目录列出来,用这个函数跑一遍,你就知道接下来该手动处理哪些东西。这种方法比在资源管理器里面右键看属性要快太多,而且可以一次看十几个目录。
6.2 多级清理策略:轻量、标准、深度
写脚本这东西,最怕的就是一刀切。后来我想了一个办法,给清理脚本增加三个模式:
- 轻量模式:只清理用户临时目录和回收站,耗时几秒,安全系数极高,适合每天定时跑。
- 标准模式:在轻量模式基础上加上系统临时目录、Windows更新缓存、缩略图缓存,适合每周跑一次。
- 深度模式:标准模式基础上启动 DISM 组件清理、清理浏览器缓存、清理旧日志,耗时十几分钟到半小时,适合每月跑一次。
实现方式很简单,脚本开头加一个参数:
param( [ValidateSet("lite", "standard", "deep")] [string]$Mode = "standard" ) switch ($Mode) { "lite" { $cleanWinUpdate = $false; $cleanBrowser = $false; $cleanDism = $false } "standard" { $cleanWinUpdate = $true; $cleanBrowser = $false; $cleanDism = $false } "deep" { $cleanWinUpdate = $true; $cleanBrowser = $true; $cleanDism = $true } }在各个清理段落的 if 判断里加上对应开关就行。然后任务计划程序里建三个任务,分别调度不同模式,完美做到“日常不折腾、定期大扫除”。
6.3 关于“设备老化测试全自动执行脚本”里的思路借鉴
搜索热搜词里看到“设备老化测试全自动执行脚本”,这让我想到清理脚本其实也可以往这个方向扩展。设备老化测试的核心思路是持续监控设备状态,自动记录数据,发现异常自动处理——清理脚本完全可以借用同样的思路,比如加上磁盘剩余空间监控功能:
if ((Get-PSDrive C).Free / 1GB -lt 20) { Write-Log "C盘剩余空间低于20GB,开始自动清理" # 调用标准清理流程 & $PSScriptRoot\Clean-CDrive.ps1 -Mode standard } else { Write-Log "C盘剩余空间充足,本次跳过清理" }把这个监控脚本做成计划任务,每天执行一次,它就能自动判断是否需要清理。这种做法比固定每天跑一次清理脚本更聪明,它把“清理”从定时动作变成了条件触发动作,大幅减少对系统的无效操作。我现在的个人电脑就是这么配置的,跑了大半年,C盘空间一直稳定在安全线以上,基本没再手动作业过。
6.4 脚本的本土化调整建议
最后说一个因地制宜的点。网上很多清理脚本是直接从英文论坛抄的,清理的目录也是英文系统默认路径。但国内用户环境普遍用的应用是微信、QQ、钉钉、企业微信这些,它们的缓存目录往往在Documents、AppData和聊天软件的专门目录下,不在外国脚本的清单里。
以微信为例,它的文件存储默认位置在C:\Users\用户名\Documents\WeChat Files,这个目录里除了聊天记录,还有大量图片和视频缓存。清理的时候千万不能整个删除,否则聊天记录全没了。正确做法是进入这个目录,找到对应微信号的子目录,再清理里面的FileStorage\Cache、FileStorage\Video这些纯缓存子目录。这块内容是脚本无法完全自动化的,因为每个人的微信存储路径不一致,所以我建议你根据自己的实际使用软件,把这类路径逐个加进脚本的白名单里定期清理。
我在文档注释里也留了这些自定义路径的位置,看到脚本里那段注释“在此添加你常用的第三方软件缓存路径”,就是提醒使用者根据自己的软件环境继续扩展。清理脚本不是写完了就一劳永逸的,它是一个随着你使用习惯不断迭代的小项目。
自己在实际使用这套脚本的过程中,最大的体会就是“克制”两个字。别看脚本写出来能一键清理好几个G,但设计思路每一步都在想怎么少删、怎么稳删。清理工具不是越激进越好,而是把一个动作重复做、稳定做,长期下来系统盘才会一直保持健康。你从手动清理过渡到脚本清理之后,就会发现每隔一段时间跑一次脚本已经变成一种习惯,看着日志里持续稳定的释放数据,比那些花里胡哨的清理软件界面让人安心得多。