
Windows 11 用久了C 盘爆红几乎是必经之路。很多人第一反应就是去下载各种清理大师结果清理半天Windows Update 缓存删掉了、临时文件清空了没过几天又红了。真正让 C 盘迅速膨胀的往往是那些隐藏极深的用户目录和 AppData 缓存尤其对于经常装开发工具、跑大型软件、折腾虚拟机的人来说C 盘就是个无底洞。这篇文章就是来解决这个问题的。我会把 AppData 和用户文件夹的迁移原理讲清楚然后给出已经写好的迁移脚本你在 PowerShell 里改一下目标盘符就能直接用。适合 C 盘空间紧张、又想保留现有系统不想重装的朋友特别是经常装 VS、Unity、Android SDK、Docker 这类软件的开发者和折腾党能一次性释放十几个 G 甚至几十个 G。1. 动手前先体检搞清楚 C 盘空间到底被谁吃掉了1.1 别急着删先把“吃空间大户”找出来我见过太多人一上来就删 AppData\Local\Temp结果把正在运行的软件缓存删了轻则软件报错重则直接闪退。真正安全的做法是先统计再动手。Win11 有一个比较隐蔽的入口设置 → 系统 → 存储 → 显示更多类别。这里会列出系统和保留空间、应用和功能、临时文件等大类。但这只是汇总级别看不到具体是哪个子目录在膨胀。我习惯直接用 PowerShell 按目录统计大小一条命令就能把 AppData 下各子目录的体积排出来Get-ChildItem -Path $env:LOCALAPPDATA -Directory -Force -ErrorAction SilentlyContinue | ForEach-Object { $size (Get-ChildItem -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum [PSCustomObject]{ 目录 $_.FullName 大小MB [math]::Round($size / 1MB, 2) } } | Sort-Object 大小MB -Descending | Select-Object -First 15 | Format-Table -AutoSize跑完之后基本就能定位到问题源头了。我经手的机器里C 盘爆满的元凶通常集中在以下几个目录你可以对照自己的电脑看C:\Users\用户名\AppData\Local\Temp——大量软件解压包、安装残留、pip/npm 临时下载文件动辄十几个 GC:\Users\用户名\AppData\Local\CrashDumps——软件崩溃转储文件很多应用崩溃后会自动写 DMP 文件积少成多C:\Users\用户名\AppData\Local\NVIDIA\DXCache——显卡着色器缓存更新驱动或玩大型游戏时会疯涨C:\Users\用户名\AppData\Local\Packages——UWP 应用数据里面包括微软商店应用、部分预装软件的数据C:\Users\用户名\下载、桌面、文档——用户自己存放的文件很多人习惯性全堆在桌面1.2 区分“可迁移”和“只能清理”的文件这是一个非常关键的概念很多人就是在这一步踩坑。用户目录下的文件其实分为两种一种是自己放的资料另一种是系统或软件生成的缓存。自己放的资料比如桌面的文档、下载的安装包、文档目录下的工作内容这类文件适合整个迁移到 D 盘或其他分区迁移后你还可以继续正常访问只是物理位置变了。软件缓存类则要分情况。比如 Temp 目录里的内容绝大多数属于临时数据直接清理掉更省事根本不需要迁但像 NVIDIA 的 DXCache、某些大型开发工具的缓存目录每次重装驱动或重装软件都会重新生成如果软件本身支持配置缓存路径那就重新指定路径如果不支持才考虑用符号链接做重定向。至于 AppData\Local\Packages这里我要特别强调不建议迁移整个 Packages 目录。它里面是 UWP 应用的挂载数据包含应用权限声明和本地数据库强行移动会导致微软商店应用全部无法打开。这个目录的正确处理方式是对里面的单个应用做“移动”操作在设置 → 系统 → 存储 → 应用里逐个改存储位置而不是在资源管理器里剪切。2. 迁移思路设计为什么我推荐“已知文件夹重定向 选择性链接”而不是整体搬走2.1 整体迁移用户文件夹的坑在哪里网上很多教程会教你把整个 C:\Users 迁移到 D 盘听着很美好实际坑得一批。Windows 的用户目录和系统的耦合非常深注册表里有大量路径是硬编码指向 C:\Users\用户名\ 下的具体目录。除非你同时对注册表做完整翻新否则迁移后会出现文件资源管理器某些位置打不开、命令行工具默认路径失效、部分软件配置找不到的问题。另外系统更新和 Windows 组件修复时有可能会重建这些目录如果你只是把文件剪切走没有同步创建好目录联接就会出现一个怪现象桌面上的文件夹明明存在但你查看 C 盘属性时发现空间并没有释放因为系统在原来位置重新生成了同名目录。所以我的思路是分层处理用户资料目录用系统自带的重定向功能让系统自己去处理注册表和权限问题AppData 里的纯缓存型目录用目录联接junction方式做重定向这样应用读取路径时还是原来的 C 盘路径但实际写入的是 D 盘空间。2.2 为什么用目录联接而不是环境变量修改有同学可能会问直接把 TEMP 环境变量改到 D 盘不就行了这个思路对了一半。环境变量改了之后新的临时文件确实会写到 D 盘但已经存在于 C 盘 Temp 里的文件不会自动搬走而且很多应用写入临时文件时用的不是环境变量路径而是直接调用 GetTempPath这个函数返回的虽然也是环境变量对应的值但个别软件会自己拼接 C:\Users...\Temp根本不读环境变量。目录联接mklink /J的好处是它在文件系统层面做了一层透明映射。只要是访问 C:\Users\用户名\AppData\Local\Temp 的路径无论是软件直接拼接的还是通过 API 获取的都会自动落到 D 盘对应的目标目录。应用层面完全感知不到路径变了兼容性最好。需要注意的是目录联接和符号链接mklink /D不是一回事。符号链接在跨分区时可能被部分软件拒绝操作而目录联接专门处理本机目录重定向稳定性高得多。我在迁移时一律用 /J 参数创建联接。2.3 制定迁移优先级按风险和收益排序我的建议是这样的高风险高收益的目录优先迁移比如下载、桌面、文档因为这几个目录往往体积巨大而且是纯用户资料不会影响系统运行。接下来是文档里的“微信文件”“QQ 文件”这类社交软件数据它们一般也在文档目录下或者 AppData 里体积动辄几个 G。中等风险的是 Temp 和 CrashDumps它们优先考虑清理如果要迁移也只迁移目录本身不要迁移里面的历史文件。低风险但收益小的是浏览器缓存目录浏览器本身提供清理入口用系统功能清理就行。Packages 目录里的 UWP 应用数据属于高风险不建议直接迁移而是逐一手动移动应用。3. 实操手动迁移用户文件夹的完整步骤3.1 桌面、下载、文档、图片、音乐、视频的标准迁移流程在动手之前先关闭所有正在运行的程序特别是文件资源管理器窗口如果正在从某个文件夹读写文件迁移时会提示文件被占用。拿“文档”举例右键点击文档文件夹 → 属性 → 位置 → 移动选择 D 盘目标目录比如 D:\UsersData\Documents。系统会询问是否把原位置的文件移动到新位置这里我建议点“是”。如果文件很大会花几分钟耐心等完。移动完成后原位置就只剩一个空壳实际文件都在 D 盘了。很多人不知道这个重定向是可以随时取消的再右键 → 属性 → 位置 → 还原默认值就能回到 C 盘默认位置。所以即使迁错了也可以恢复风险很低。桌面、下载、图片、音乐、视频的标准迁移流程是一样的只是文件夹名字不同。一个人如果把所有已知文件夹都迁移了通常能释放 5~20 个 G具体看你之前的文件堆积量。3.2 变更“新内容保存位置”这是个很容易被忽略的设置在设置 → 系统 → 存储 → 高级存储设置 → 保存新内容的位置。这里可以分别把新的应用、文档、音乐、图片、视频和电影电视节目默认保存到其他驱动器。这项设置改动后新安装的应用默认会装到 D 盘以后就不会再往 C 盘塞大体积软件。注意一点它只影响新装的应用已有应用不会被移动需要回前面说的“应用”列表里逐个移动。3.3 迁移过程出现“文件被占用”怎么办最常见的情况是某些后台进程在读取文档目录里的文件比如 OneDrive、微信、企业微信、微信开发者工具它们的文件监听服务会锁定一批文件。解决方案有两个一是用 Process Explorer 或系统自带的资源监视器搜索被占用的文件句柄然后结束对应进程二是更省事的做法重启电脑后不要打开任何软件第一时间去执行迁移操作。我就用第二个方法成功率高得多。4. 实操AppData 安全迁移的手工操作记录4.1 迁移 Temp 缓存目录Temp 目录建议先清理再迁移。操作顺序先删旧内容再建目标目录最后创建联接。把 C:\Users\用户名\AppData\Local\Temp 下所有文件选中删除会有部分被占用删不掉跳过即可。然后创建 D:\Cache\Temp 目录再以管理员身份打开 CMD执行mklink /J C:\Users\用户名\AppData\Local\Temp D:\Cache\Temp这个命令要求源路径不存在所以必须确保 C 盘原有 Temp 目录已被删除或重命名。我强烈建议先把原 Temp 重命名成 Temp_Old然后创建联接等确认一切正常后再删除 Temp_Old。而不是直接删除原目录因为万一联接创建失败原目录还在不至于系统崩溃。实际上我在实际操作时就是先把 Temp 改名为 Temp_Old创建联接成功后再手工删除 Temp_Old 里的历史文件。这样系统一直有可用的 Temp不会出现环境变量指向不存在的路径导致软件大面积报错。4.2 迁移 CrashDumps 转储目录CrashDumps 目录通常不大但有时候某个软件反复崩溃会瞬间产生几百个 DMP 文件每个几十兆。迁移时先把原目录内容转移到目标盘然后再做联接。使用 robocopy 是最稳的robocopy C:\Users\用户名\AppData\Local\CrashDumps D:\SystemCache\CrashDumps /E /COPYALL /R:1 /W:1COPYALL 会保留安全属性、所有者信息避免迁移后目录权限不对导致系统无法写入。复制完成后确认文件数一致再重命名原目录创建联接。4.3 迁移 NVIDIA DXCache 着色器缓存这个目录只有在显卡驱动更新或运行大量 3D 应用时才会增长但一涨就是几个 G。迁移前先关掉所有正在运行的游戏和图形软件因为图形驱动正在频繁读写这个目录。迁移方式一样robocopy 复制到 D 盘然后 mklink /J 联接回去。但是有一个注意事项显卡驱动更新时驱动安装程序有时会删除整个 DXCache 目录再重建如果做成了联接它可能把联接本身也删掉导致应用后续找不到路径。不过实测大多数情况只是清空内容联接结构还是保留的。为了保险建议显卡驱动更新频率不高趋势的收益还是大于风险。4.4 重点提醒哪些目录坚决不能动AppData\Local\Packages 不要动里面每个子目录对应一个 UWP 应用直接做联接会导致应用无法启动或闪退。如果确实有应用占地方去“设置 → 应用”里找到目标应用点击“移动”把它整体迁到其他盘。AppData\Roaming 也不要整体迁移。这里面存放的是应用配置和登录状态很多应用初始化时会重新读取这个位置哪怕是目录联接也可能触发写入异常。ProgramData 更不要动它属于系统级数据目录迁移会直接破坏系统软件环境。5. 一键脚本把上面的手动流程全部自动化5.1 脚本设计思路我之前手动折腾过好几台机器后来把整个流程写成了 PowerShell 脚本。它做的事情分三块把已知用户文件夹做系统级重定向把 AppData 里的纯缓存目录做清理重定向把关键目录的迁移过程写入日志方便排查问题。脚本用管理员身份运行目标目录通过参数传入。比如你想把数据迁到 D 盘就执行.\Safe-Migrate.ps1 -TargetBase D:\UsersData脚本默认只迁移已知文件夹和三个 AppData 缓存目录不会碰 Packages 和 Roaming安全限度较高。如果你不想迁移某个类别用 -SkipKnownFolders 或 -SkipCacheFolders 参数跳过。5.2 完整脚本内容# .SYNOPSIS Win11 C盘瘦身安全迁移用户文件夹与AppData缓存目录 .DESCRIPTION 用法管理员PowerShell .\Safe-Migrate.ps1 -TargetBase D:\UsersData 参数 -TargetBase 目标根目录脚本会在这个目录下创建 Users、SystemCache -SkipKnownFolders 跳过桌面/文档/下载/图片等已知文件夹迁移 -SkipCacheFolders 跳过Temp/CrashDumps/DXCache缓存目录迁移 .NOTES 建议运行前关闭所有软件迁移过程中不要打开文件资源管理器 # param( [Parameter(Mandatory $true)] [string]$TargetBase, [switch]$SkipKnownFolders, [switch]$SkipCacheFolders ) # ---------- 环境检查 ---------- if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] Administrator)) { Write-Host [错误] 请右键 PowerShell 并选择以管理员身份运行 -ForegroundColor Red exit 1 } $userName $env:USERNAME $userRoot C:\Users\$userName $logFile Join-Path ([System.IO.Path]::GetTempPath()) SafeMigrate-$(Get-Date -Format yyyyMMddHHmmss).log function Write-Log { param([string]$Message, [string]$Color Gray) $time Get-Date -Format yyyy-MM-dd HH:mm:ss [$time] $Message | Tee-Object -FilePath $logFile -Append Write-Host $Message -ForegroundColor $Color } # ---------- 通用迁移函数robocopy 目录联接 ---------- function Move-FolderWithLink { param( [string]$Source, [string]$DestRoot, [string]$LinkName ) if (-not (Test-Path $Source)) { Write-Log [跳过] 源目录不存在: $Source -Color Yellow return } $target Join-Path $DestRoot $LinkName if (Test-Path $target) { Write-Log [跳过] 目标目录已存在: $target -Color Yellow return } New-Item -ItemType Directory -Path $target -Force | Out-Null Write-Log [复制] $Source - $target robocopy $Source $target /E /COPYALL /DCOPY:DAT /R:1 /W:1 /XJ /NFL /NDL /NP if ($LASTEXITCODE -ge 8) { Write-Log [错误] robocopy 复制失败退出码 $LASTEXITCODE请检查日志 -Color Red exit 1 } $backup $Source_Old_$(Get-Date -Format yyyyMMddHHmmss) Rename-Item -Path $Source -NewName (Split-Path $backup -Leaf) Write-Log [备份] 原目录已重命名为 $backup cmd /c mklink /J $Source $target 21 | Out-Null if ((Get-Item $Source).LinkType -eq Junction) { Write-Log [联接] 创建成功: $Source - $target -Color Green } else { Write-Log [错误] 目录联接创建失败请手工检查 -Color Red exit 1 } } # ---------- 1. 用户已知文件夹迁移使用系统位置重定向 ---------- if (-NOT $SkipKnownFolders) { Write-Log 开始迁移已知文件夹 $knownFolders ( { Name Desktop; Reg Desktop; SubDir Desktop }, { Name Documents; Reg Personal; SubDir Documents }, { Name Downloads; Reg {374DE290-123F-4565-9164-39C4925E467B}; SubDir Downloads }, { Name Pictures; Reg My Pictures; SubDir Pictures }, { Name Music; Reg My Music; SubDir Music }, { Name Videos; Reg My Video; SubDir Videos } ) $shellFolders $env:APPDATA\Microsoft\Windows\Libraries $userShell HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders $shell HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders foreach ($row in $knownFolders) { $sourceFolder Join-Path $userRoot $row.SubDir $targetFolder Join-Path (Join-Path $TargetBase Users) $row.SubDir if (-not (Test-Path $sourceFolder)) { Write-Log [跳过] $($row.Name) 源目录不存在 -Color Yellow continue } New-Item -ItemType Directory -Path $targetFolder -Force | Out-Null Write-Log [复制] $($row.Name): $sourceFolder - $targetFolder robocopy $sourceFolder $targetFolder /E /COPYALL /DCOPY:DAT /R:1 /W:1 /XJ /NFL /NDL /NP if ($LASTEXITCODE -ge 8) { Write-Log [错误] $($row.Name) 复制失败退出码 $LASTEXITCODE -Color Red continue } # 更新注册表路径 $regValue $row.Reg Set-ItemProperty -Path $userShell -Name $regValue -Value $targetFolder -Type ExpandString Set-ItemProperty -Path $shell -Name $regValue -Value $targetFolder -Type ExpandString # 清空原文件夹下的内容迁移完成后再提示 Write-Log [完成] $($row.Name) 已重定向原目录可手动检查后删除 -Color Green } } else { Write-Log 跳过已知文件夹迁移 } # ---------- 2. AppData 缓存目录迁移 ---------- if (-NOT $SkipCacheFolders) { Write-Log 开始迁移 AppData 缓存目录 $cacheSource Join-Path $env:LOCALAPPDATA Temp Move-FolderWithLink -Source $cacheSource -DestRoot (Join-Path $TargetBase SystemCache) -LinkName Temp $crashSource Join-Path $env:LOCALAPPDATA CrashDumps Move-FolderWithLink -Source $crashSource -DestRoot (Join-Path $TargetBase SystemCache) -LinkName CrashDumps $dxSource Join-Path $env:LOCALAPPDATA NVIDIA\DXCache Move-FolderWithLink -Source $dxSource -DestRoot (Join-Path $TargetBase SystemCache) -LinkName NVIDIA-DXCache } else { Write-Log 跳过 AppData 缓存目录迁移 } Write-Log 全部操作执行完毕建议重启电脑下载验证。 Write-Log 日志路径: $logFile5.3 脚本关键点解读第一个容易忽视的地方是robocopy的退出码。robocopy 返回 0 到 7 都表示成功8 以上表示有错误所以判断条件用的是-ge 8而不是直接判断是否等于 0。第二个关键是mklink /J必须在重命名原目录之后执行否则 Windows 会提示源目录已存在无法创建联接。脚本里先做 Rename-Item 备份再创建联接这个顺序不能颠倒。第三个关键是通过注册表User Shell Folders重定向已知文件夹。这里用Set-ItemProperty -Type ExpandString是因为注册表里的路径支持环境变量设置成%USERPROFILE%\Documents这种格式也没问题但直接用绝对路径更稳妥。使用脚本后建议先重启一次检查桌面文档是否都能正常打开再删除C:\Users\用户名下重命名出来的_Old目录。脚本只是把原目录重命名备份了并没有自动删除这是刻意的设计——万一迁移后系统出现问题你还有后悔药吃。6. 常见问题与排查技巧实录6.1 迁移后桌面路径还是显示 C 盘遇到过好几次明明用了脚本重定向重启后桌面还是走 C 盘原来的路径。原因基本是重定向只改了当前用户配置但部分系统组件在初始化时仍会读取旧值。解决办法是检查注册表HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders中 Desktop 的值是否指向新路径。如果是旧路径手动改一下如果是新路径但桌面仍显示 C 盘内容那就要检查是否有个 Explorer 进程一直占用旧目录注销重登一次即可。6.2 迁移后应用崩溃或配置丢失这种情况大概率是你动了不该动的目录比如把 Roaming 也迁移了或者 Migration 了 Packages。我这里强调过Roaming 和 Packages 不能动它们包含应用的配置数据库和权限文件迁移后应用根本找不到自己的设置。遇到这种事故最快的恢复办法是回到 C 盘原位置将备份的_Old目录恢复回来——删除联接把原目录名字改回。要保持冷静不要删掉备份目录。6.3 目录联接创建成功但 C 盘空间没释放这说明原目录里的历史文件还在_Old备份目录里躺着并没有被自动删除。这是脚本刻意为之的安全机制。你在确认系统稳定之后手动删除C:\Users\用户名\AppData\Local\Temp_Old_xxx这类文件夹就行。不过有一种特殊情况要注意如果原目录里还有文件被某个后台进程占用删除时会提示“操作无法完成”此时重启电脑后再删或者用 Unlocker 之类的工具解锁后删除。6.4 迁移后微信或企业微信无法发送图片频繁出现的一个问题。微信默认会把接收文件和缓存放在文档目录的“WeChat Files”下如果你迁移了文档文件夹微信自身的数据跟着走了但图片发送时引用的临时缓存目录还留在 C 盘导致文件索引不一致。解决方法是微信内设置 → 文件管理 → 更换存储位置把微信的独立数据目录指到 D 盘的一个新路径别放在文档文件夹的子目录里。这样既避免微信数据跟着文档迁移来回移动也减少两个系统功能之间的耦合。6.5 迁移后 C 盘仍然显示空间不足用户文件夹和 AppData 迁移完C 盘可能还是红。这时要去查另外几个大头C:\Windows.old重装系统后的残留用磁盘清理功能清、C:\hiberfil.sys休眠文件、C:\pagefile.sys虚拟内存交换文件。休眠文件用powercfg /h off关闭休眠即可释放前提是你不用“快速启动”这个功能。虚拟内存文件如果非必要可以迁移到其他盘右键此电脑 → 属性 → 高级系统设置 → 性能设置 → 高级 → 虚拟内存更改把 C 盘设置为无分页文件然后给 D 盘分配相同大小。6.6 实测表现与避坑心得我在十几台不同配置的机器上跑过这套流程。最容易出问题的是那些装了大量 UWP 应用并长期不关机的机器迁移前建议在“设置 → 应用”里逐一把大型 UWP 应用迁走而不是依赖缓存目录清理。开发环境机器要注意如果你装了 Android SDK、Docker Desktop、Anaconda这些工具的缓存目录重置会出现“找不到路径”的错误。因为这些工具通常会在安装向导里配置缓存路径迁移前先去它们设置里把缓存目录改到 D 盘再做 AppData 缓存迁移避免互相冲突。最后再分享一个小技巧每次给朋友或者客户的机器迁移完我都会顺手清理一次 Windows 更新缓存命令是Dism.exe /Online /Cleanup-Image /StartComponentCleanup跑完后 C 盘系统占用又能降下来一块。搭配这篇里最核心的迁移思路C 盘红条基本就能彻底变成蓝色了。