
很多看起来像软件有 bug的问题最后都指向同一件事——Windows 文件目录结构没摸清。我印象最深的一次是帮人排一个 Redis 服务他改了三遍redis.windows.conf重启服务后端口还是 6379气得差点卸载重装。真相很朴素他改的是解压目录里那份配置而注册成服务的那份配置在另一个路径下服务启动时读的是后者。类似的还有hosts 改了不生效Python 装了三个版本pip 却总装到别的地方C 盘莫名少了 100G。这些问题的排查链路最终都会落到目录结构、环境变量和数据落点这三件事上。这篇就把 Windows 的目录结构从根目录一路拆到AppData讲清楚每个目录归谁管、软件默认把数据写在哪、命令行怎么快速定位任何程序的真实数据路径。不管你是刚装完系统的开发新手还是天天给同事收拾环境的老手看完都能自己动手把机器盘点一遍。1. 从一个改了三遍配置却不生效的故障说起1.1 根目录下这些文件夹各归谁管先建立一张顶层地图。打开资源管理器看到盘符根目录一排文件夹里其实只有三类系统自己建的、安装程序建的、你自己建的。分工大致如下。目录归属说明能不能删C:\Windows系统操作系统本体、驱动、组件存储绝对不要动C:\Program Files应用64 位程序的默认安装位置按需卸载别手删C:\Program Files (x86)应用32 位程序在 64 位系统上的默认位置同上C:\ProgramData应用全机器共享的程序数据默认隐藏看具体子目录C:\Users用户每个账号的配置、文档、缓存别整体删C:\Recovery系统恢复环境相关文件不要动C:\PerfLogs系统性能日志预留目录99% 的机器是空的可忽略这里有个非常容易踩的细节Program Files (x86)不是老旧目录它是 WOW64 机制的一部分。64 位 Windows 上一个 32 位的安装包默认会往Program Files (x86)里装而它读写的注册表也会被重定向到 Wow6432Node 分支。所以你在排查同一个软件装了两份、配置文件找不到的时候第一步不是打开配置文件而是先确认你面对的是 32 位还是 64 位的那一份。看目录本身是最快的判断方式比查进程还快。还有一类命名会让你误判中文系统里资源管理器把C:\Users显示成用户把C:\ProgramData显示成程序数据。这不是两个目录是同一个目录的本地化显示靠目录里的desktop.ini实现。所以在资源管理器地址栏里复制出来的中文路径粘到命令行里往往报错。养成习惯看目录结构时永远以命令行的英文真实路径为准。1.2 为什么dir看不到ProgramDataProgramData、Users里的部分目录、根目录下的pagefile.sys、hiberfil.sys、swapfile.sys都有一个共同属性隐藏Hidden甚至系统System。资源管理器默认不显示隐藏项dir命令也不显示于是很多人会得出这个目录不存在的错误结论。正确的查看方式有三种我都常用:: 显示当前目录下包含隐藏、系统属性的所有条目 dir /a :: 查看单个文件的完整属性H 隐藏、S 系统、R 只读、A 存档 attrib C:\hiberfil.sys# 递归列出隐藏项只看一层 Get-ChildItem C:\ -Force # 查某类隐藏目录是否真实存在 Test-Path C:\ProgramData\Docker资源管理器那边则是查看里勾选隐藏的项目再看选项里取消隐藏受保护的操作系统文件。我个人的建议是日常别长期开着显示系统文件容易误删需要排查时临时打开查完关掉。pagefile.sys、hiberfil.sys、swapfile.sys这三个根目录钉子户值得单独说。它们不是普通文件是虚拟内存分页文件、休眠文件、UWP 应用交换文件。它们在资源管理器里显示为几十 G 是正常的hiberfil.sys的大小约等于物理内存的 40% 到 100%取决于休眠模式配置。清理这两个文件只能走系统设置关闭休眠、调整虚拟内存直接删除会立刻报文件正在使用。1.3$Recycle.Bin、System Volume Information的真实用途$Recycle.Bin是回收站的真身按 SID 分子目录每个用户账号一个。有时候你会发现自己清空了回收站这个目录还是占着几十 G——通常是别的账号残留的或者存在权限异常导致回收站索引损坏。这种时候用系统自带的磁盘清理工具最稳手动删容易留下坏索引。System Volume Information是系统还原点、卷影副本VSS、索引数据库的存放地。它默认拒绝一切访问icacls看权限会显示只有 SYSTEM 有完全控制。很多备份软件、索引软件占用的空间都在这里。要回收它的空间正确操作是在系统属性 → 系统保护里调整最大使用量或删除还原点而不是手动进目录。我见过有人用管理员权限强改权限后清空这个目录结果系统还原彻底失效且卷影副本服务报错只能重装。2.C:\Windows内部分层System32 的重定向魔法与 DriverStore2.1 System32 和 SysWOW64 到底谁是谁这是 Windows 目录结构里最反直觉的一处。在 64 位系统上C:\Windows\System32放着64 位系统文件。C:\Windows\SysWOW64放着32 位系统文件。名字里带 32 的装 64 位带 64 的装 32 位看名字猜必错。原因要追到 WOW64Windows 32-bit on Windows 64-bit的重定向机制一个 32 位进程去访问C:\Windows\System32时系统会在文件系统层面把它悄悄重定向到SysWOW64同理它访问HKLM\Software注册表也会被重定向到Wow6432Node。这样老程序写死了System32也能拿到自己该用的 32 位 DLL不会和 64 位 DLL 冲突。这个机制带来的排查陷阱很典型你在 32 位程序里打印出来的路径是C:\Windows\System32\xxx.dll实际文件在SysWOW64下。要找程序真正加载了哪个 DLL别靠日志打印的路径用工具看# 看进程加载的模块真实路径需要管理员权限 Get-Process -Name myapp | Select-Object -ExpandProperty Modules | Select-Object ModuleName, FileName只有 64 位进程或者用%windir%\Sysnative这个虚拟别名才能看到真正的System32。Sysnative是给 32 位进程访问 64 位 System32 的唯一正规入口做安装脚本时经常用到值得记一笔。2.2drivers\etc一堆网络配置的窝点C:\Windows\System32\drivers\etc是每个网络排查都会碰到的目录它小得不起眼但里面几乎每个文件都有用文件作用什么时候需要改hosts本地域名解析优先级高于 DNS本地域名映射、屏蔽、联调lmhosts.samNetBIOS 名称解析示例文件基本不用networks网络名称到网络号的映射极少用protocol协议名到协议号的映射不要改services服务名到端口号的映射极少用hosts是这里面唯一需要经常动的。它的解析优先级比 DNS 查询高格式是IP 空白 域名行首加#注释。改完之后有三件事必须确认否则你会觉得改了没用文件没有扩展名。记事本另存为会自动加.txt必须选所有文件并把名字引号包起来hosts。保存后有管理员权限文件权限没有被改坏。刷新 DNS 缓存ipconfig /flushdns。浏览器自身还有 DNS 缓存必要时重启浏览器或用无痕窗口验证。我一般用这条命令直接验证解析结果比 ping 更干净nslookup example.local 127.0.0.12.3DriverStore\FileRepository驱动为什么有这么多个版本C:\Windows\System32\DriverStore\FileRepository是驱动仓库每个驱动占一个以驱动名加哈希后缀命名的子目录比如nv_dispi.inf_amd64_xxxxxxxx。装显卡驱动、串口驱动CH340 这类、网卡驱动时安装包先解压到这里再由系统装配。理解这个目录能解决两类典型问题。第一类是驱动装不上、提示数字签名问题老驱动签名过期或被吊销时安装会被拒。处理方向是换官方最新驱动包而不是强行禁用签名校验——那属于破坏系统完整性后患不小。第二类是我想彻底卸载驱动再重装很多人以为删掉FileRepository里对应目录就行实际上这会让驱动仓库索引和实际文件不一致卸载或者重新安装时会报错。正确做法是用设备管理器卸载并勾选删除驱动程序软件或者用pnputil命令行管理:: 列出第三方驱动包 pnputil /enum-drivers :: 按已发布的名称删除指定驱动包 pnputil /delete-driver oem12.inf /uninstallpnputil的好处是它走的和系统安装程序同一条链路索引会同步更新。这个命令我在处理打印机驱动残留、串口驱动冲突时用得最多。顺带说一下相关日志位置驱动安装的详细日志在C:\Windows\INF\setupapi.dev.log这个文件记录了每一次设备安装的完整过程。当你遇到某个设备反复安装失败的时候翻这个日志的最后几百行基本能看到失败的具体原因比看事件查看器精准得多。2.4 WinSxS、Installer、Temp能碰的和别碰的C:\Windows\WinSxS是组件存储它体积经常十几个 G看起来像垃圾实际上是系统更新的硬链接仓库。你在资源管理器里看到的体积是虚高的因为里面大量文件是硬链接重复计算了。删它的结果不是释放空间而是系统更新永久损坏、SFC 修复失败。真要回收空间走官方命令DISM /Online /Cleanup-Image /StartComponentCleanup /ResetBase注意/ResetBase会让已安装的更新无法卸载机器如果还在调试阶段就别加这个参数。C:\Windows\Installer是 MSI 安装包的缓存专门存放.msi和.msp文件。这个目录千万别清它不是安装包垃圾而是软件修复、卸载、打补丁时必需的源文件。删了之后会看到找不到安装源无法卸载这种死循环报错。同理C:\Windows\Temp和%TEMP%可以清但操作前要关掉所有应用否则正在运行的安装程序会失败。3. 用户目录与 AppData软件把数据写在哪的真实规律3.1C:\Users\用户名这一层都有什么用户目录是日常打交道最多的一层结构大体固定Desktop、Documents、Downloads、Pictures、Videos面向用户的资料目录。AppData程序数据默认隐藏下面分三级下面单独讲。.ssh、.gitconfig、.npmrc、.condarc、.m2、.gradle各工具的约定配置目录以点开头Unix 习惯带进 Windows 的产物。NTUSER.DAT等注册表配置单元文件隐藏且锁定不要动。这里有个现代环境特有的坑如果启用了 OneDrive 的备份文件夹功能Desktop、Documents、Pictures会被重定向到C:\Users\用户名\OneDrive\Desktop之类的路径。命令行里%USERPROFILE%\Desktop可能已经是个重定向点。所以当你写脚本处理用户桌面时别硬编码路径用 shell 已知文件夹变量最稳# 取真实的桌面路径兼容 OneDrive 重定向 [Environment]::GetFolderPath(Desktop)再说一个常见困惑C:\Users下除了你的账号还有个Public公用目录以及Default新用户模板默认隐藏。Default是新账号的配置模板你新建账号时看到的初始桌面就是从这里复制的。有些企业镜像会把默认配置改在这个目录里这也解释了为什么新建账号自动装了一堆东西。3.2 Roaming / Local / LocalLow三选一的逻辑AppData下面的三个子目录不是随便分的选择逻辑很清楚子目录物理路径变量设计意图典型内容Roaming%APPDATA%跟随账号漫游到其他机器编辑器配置、软件许可信息、用户偏好Local%LOCALAPPDATA%只属于本机体积可能很大缓存、日志、索引、虚拟机磁盘LocalLow%USERPROFILE%\AppData\LocalLow低完整性级别进程使用受保护模式下的浏览器插件数据判断一个软件配置在哪的实用方法先看%APPDATA%那里是配置再看%LOCALAPPDATA%那里是数据和缓存。多数软件两处都写。这个规律在排查重置配置不生效的时候极其管用——你删了Roaming下的配置但Local下还有一份缓存状态重启后软件又把旧配置恢复了。3.3 拿几个真实软件验证规律把规律套到常接触的工具上验证一遍会记得更牢。Git for Windows程序体在C:\Program Files\Git系统级配置在C:\Program Files\Git\etc\gitconfig用户级配置在%USERPROFILE%\.gitconfig。三层配置按系统、全局、仓库的顺序覆盖。所以我配了 user.name 但提交还是旧名字通常是仓库级.git/config覆盖了全局配置。用这三条命令查覆盖链git config --system --list git config --global --list git config --local --listMiniconda / Anaconda单用户安装默认落在%USERPROFILE%\miniconda3全用户安装落在C:\ProgramData\miniconda3。环境目录在安装目录的envs下另外%USERPROFILE%\.conda\environments.txt记录了所有环境的路径清单。这个清单文件是排查conda 找不到环境的关键环境被手动移动过之后清单里还是老路径conda env list就会列出一堆失效环境。JDK默认在C:\Program Files\Java\jdk-17这类路径。真正决定用哪个 JDK 的是JAVA_HOME和PATH里的bin顺序而不是目录本身。装多个版本时改JAVA_HOME比改PATH更可靠因为大量构建工具直接读JAVA_HOME。Docker Desktop程序装在C:\Program Files\Docker用户配置在%APPDATA%\Docker\settings.json镜像和容器数据在%LOCALAPPDATA%\Docker下的 WSL 相关目录。所以重置 Docker 设置和清空 Docker 数据是两个完全不同的操作前者删settings.json后者要动Local下的大目录千万别搞混。如果用的是 Windows 容器模式非 WSL 后端数据落点会跑到C:\ProgramData\docker下体积增长快值得定期看一眼。Redis / Elasticsearch 这类解压即用的服务它们的目录结构完全取决于你解压的位置redis.windows.conf、config\elasticsearch.yml、data、logs都在解压根目录下。风险在于注册成系统服务时服务的工作目录可能不是你解压的目录导致配置改了不生效就是开头那个案例。判断方法查服务的可执行路径。sc qc Redis sc qc elasticsearch-service-x64输出的BINARY_PATH_NAME会带上-Djava.home或工作目录参数那才是它真正读取的路径。3.4 VirtualStore往 Program Files 写配置的影子目录这是一个老程序带来的隐藏机制不知道它会浪费你很多时间。机制是这样的32 位程序试图往C:\Program Files或者HKLM\Software写入时如果没有管理员权限Windows 会把写入重定向到用户目录下的影子位置%LOCALAPPDATA%\VirtualStore\Program Files\...程序自己读到的是自己的写入结果看起来一切正常但你去真实目录里找什么也没有。排查这类问题的最快方式是直接在%LOCALAPPDATA%\VirtualStore里搜文件名Get-ChildItem $env:LOCALAPPDATA\VirtualStore -Recurse -Force | Where-Object Name -like *myapp*.iniVirtualStore只在 32 位进程且未提升权限时启用64 位程序不走这条路。这也解释了为什么同一个软件在他电脑上配置能保存在我电脑上保存了但重启就丢——一台机走的是真实目录另一台走的是虚拟化重定向。4. 环境变量与 PATH目录结构的索引层4.1 系统变量和用户变量是怎么拼接的目录结构是硬盘上的物理布局环境变量是系统查目录的索引。两者必须一起理解才有用。Windows 有两套环境变量系统级Machine和用户级User。同名变量在两处都存在时用户级的会覆盖系统级但PATH是特例——它是拼接通常系统PATH在前用户PATH追加在后。查看和对比这两个 PATH最直观的方式是分开打印# 查看当前进程生效的 PATH按分号切成数组一行一个 $env:Path -split ; # 分别看持久化的系统级和用户级 PATH [Environment]::GetEnvironmentVariable(Path,Machine) -split ; [Environment]::GetEnvironmentVariable(Path,User) -split ;这里有个高频踩坑点改完环境变量后已经打开的终端不会自动生效。cmd、PowerShell、IDE 都是启动时读一次环境变量。所以配置了但命令找不到的第一反应应该是关掉窗口重开而不是怀疑自己配错了。我见过有人因为这个把 PATH 反复加了五遍重复项。另外要提醒的是PATH的长度问题。老版本 Windows 对单个环境变量的长度有限制约 2048 字符超了会被静默截断。现在这个上限放宽了但大量安装程序不断往 PATH 里追加仍然容易变成一条几百字符的面条。定期清理 PATH 是很有必要的维护动作把失效路径、重复路径、指向已卸载软件的路径摘掉能省掉很多莫名其妙的报错。4.2 PATH 查找顺序引发的命令版本不对PATH是从左到右匹配的第一个命中就返回。这就是我装了新版本 Pythonpython -V还是旧版本的根本原因。排查方法不止一种我会同时用这两条:: cmd 下列出所有同名可执行文件 where python where node where git# PowerShell 下列出所有候选命令 Get-Command python -All | Select-Object Sourcewhere输出多条结果时第一条就是实际会被执行的那条。想固定某个版本两条路把目标目录在PATH里上移或者更推荐的做法——用无歧义的完整路径或者用版本管理工具py -3、nvm、fvm这类。顺便说一个有趣的细节cmd 的where和 PowerShell 的where不是一回事。在 PowerShell 里where是Where-Object的别名直接敲where python不会列出路径。用where.exe python或者Get-Command才靠谱。这个差异坑过很多刚切到 PowerShell 的人。4.3 260 字符长路径限制与\\?\前缀目录结构相关的经典限制是路径长度传统 API 下完整路径上限 260 个字符MAX_PATH。深层的node_modules、Python 虚拟环境、多层构建产物经常撞线报文件名或扩展名太长。几个应对层次。第一层从源头减短路径项目目录别放在C:\Users\很长的用户名\Documents\很长的项目名\...这种深层路径下改到D:\proj\这种浅路径往往立刻解决。第二层开启系统长路径支持需要注册表项配合且程序自身声明支持reg query HKLM\SYSTEM\CurrentControlSet\Control\FileSystem /v LongPathsEnabled第三层使用\\?\前缀绕过 260 限制写法是把\\?\直接拼在完整绝对路径前面dir \\?\D:\very\deep\path\with\long\name robocopy \\?\D:\src \\?\E:\dst /E注意\\?\路径必须是完整绝对路径不支持.和..也不接受正斜杠。robocopy是处理超长路径最省心的工具我在迁移大数据目录时基本都用它它原生支持\\?\且保留权限和时间戳。4.4 那些约定俗成的变量值不值得依赖除了PATH有一批变量是排查目录问题时天天用到的变量典型值用途%WINDIR%C:\Windows定位系统目录别硬编码盘符%PROGRAMDATA%C:\ProgramData定位全机器共享数据%APPDATA%...\AppData\Roaming用户配置%LOCALAPPDATA%...\AppData\Local用户数据与缓存%TEMP%/%TMP%...\AppData\Local\Temp临时文件%USERPROFILE%C:\Users\用户名用户根目录写脚本、写安装说明、写排查步骤时一律用变量而不是硬编码C:\路径。原因很实际系统盘符不一定是 C用户目录可能被重定向中文用户名和空格会让未加引号的命令直接断裂。一条经验任何拼进命令行的路径都要加引号哪怕你确信它没有空格。5. 解析目录结构的实操手法从猜到查5.1 手工排查四件套定位一个软件的数据落点我有一套固定动作四步之内基本能出答案。第一步确认可执行文件真实位置。快捷方式会骗人直接问系统where myapp或者在 PowerShell 里Get-Command myapp | Select-Object Source。如果需要更细的信息比如服务的可执行路径用sc qc 服务名或任务管理器的打开文件所在位置。第二步列目录并带上隐藏项看清子目录构成。dir /a和Get-ChildItem -Force各看一遍重点找config、conf、data、logs、cache这几个特征目录名它们基本能揭示软件的配置与数据布局。第三步看目录体积排除干扰。同样名字的目录有好几处时体积最大的那个通常是真正在用的数据目录。第四步确认写入行为。最直接的办法是改一个配置项、重启程序然后按修改时间排序看哪个文件被更新了Get-ChildItem $env:APPDATA -Recurse -Force -File | Where-Object LastWriteTime -gt (Get-Date).AddMinutes(-10) | Select-Object FullName, LastWriteTime这一招几乎万能任何程序到底把配置写哪了的问题都可以这样抓现行。注意加-Force才能看到隐藏文件递归范围要控制好别在根目录上直接跑。5.2 谁吃了 100G体积分析的正确姿势磁盘满了是最常见的一类求助。手工一层层点下去太慢工具选型上我的排序是先看整体分布的 Treemap 类工具WizTree、TreeSize Free 这类它直接读 NTFS 的 MFT扫几百万文件也就几秒再用命令行做精确定位。PowerShell 原生方案在目录少的时候够用# 统计某个目录下各子目录的体积MB降序 Get-ChildItem C:\Users -Directory -Force | ForEach-Object { $size (Get-ChildItem $_.FullName -Recurse -Force -File -ErrorAction SilentlyContinue | Measure-Object Length -Sum).Sum [PSCustomObject]{ Path $_.FullName; SizeMB [math]::Round($size/1MB,1) } } | Sort-Object SizeMB -Descending | Select-Object -First 15跑这类命令有两个注意点。一是必须有管理员权限否则大量目录读不到统计结果会严重偏小二是-ErrorAction SilentlyContinue省不掉遇到权限拒绝和路径过长时脚本会中断。如果统计结果明显比磁盘实际占用小一般就是权限或长路径导致的漏统计。按经验C 盘空间的大头通常是这几处WinSxS虚高但真实占用也不小、%LOCALAPPDATA%下的各类缓存、ProgramData下的容器与数据库数据、休眠文件、以及各家 IDE 的索引目录。定位到具体目录之后处理方式要分清楚缓存可以清数据必须迁系统组件交给官方工具。5.3 从运行中的进程反查目录有时候你知道程序在跑但完全不知道它读写哪些目录。这时候从进程反查最高效。资源监视器resmon的 CPU 页签里有个关联的句柄搜索框输入目录名或文件名片段就能列出所有打开的句柄及其所属进程。Process Explorer 的CtrlF也是同样的思路功能更强可以按句柄、DLL、线程搜索。Sysinternals 的handle.exe适合脚本化handle.exe -a myapp -u这种方式的独特价值在于它能揭示那些看不见的打开状态。比如你删不掉某个目录提示文件夹正在使用用句柄搜索立刻能看到是哪个后台进程占着——常见嫌疑是搜索索引、杀毒扫描、同步客户端和编辑器残留进程。5.4 目录迁移mklink的正确用法与三个坑C 盘空间告急时把大目录迁到别的盘、在原位置留一个链接是很有效的办法。Windows 支持两种主要形式:: 目录联接Junction不需要管理员权限即可创建仅限本地卷 mklink /J C:\ProgramData\BigData D:\BigData :: 目录符号链接Symbolic Link需要管理员或开发者模式 mklink /D C:\Link D:\Target两者在使用体验上差不多差异在于 Junction 是文件系统层的重定向、只支持本地绝对路径兼容性更好符号链接支持相对路径和跨主机但需要权限。做空间迁移我一律优先用 Junction。迁移有三个坑必须提前说。第一先确认目标程序能接受链接少数软件会自己解析真实路径比如某些反作弊、加密狗、授权校验模块看到链接会判断异常。第二迁移前停掉所有相关服务和进程迁移后用fsutil hardlink list或资源监视器确认新位置被正常读写。第三别在移动中的目录上建链接——先把数据完整复制、校验、再改名替换最后建链接顺序错了容易丢数据。robocopy C:\ProgramData\BigData D:\BigData /E /COPYALL /DCOPY:DAT /R:1 /W:1robocopy的退出码要注意0 到 7 都算正常不同位代表有文件复制、有额外文件等8 以上才是错误。写脚本判断成败时别用if errorlevel 1会把成功当失败。6. 四个高频踩坑场景的复盘6.1 Program Files 写入失败与权限够了还是不行最典型的报错是对路径的访问被拒绝发生地点几乎总在C:\Program Files和C:\ProgramData下的某个目录。原因是 NTFS 权限 UACProgram Files默认只允许管理员写入标准用户进程写入会失败或者被虚拟化重定向。判断和修复的顺序应该是这样的。先用icacls看权限确认当前账号是否在允许列表里icacls C:\ProgramData\MyApp如果权限本身没问题那多半是 UAC 令牌问题进程没有以提升权限运行。处理方式是用管理员身份运行安装程序或服务。但这里要提醒一句不要为了省事把Program Files的权限整体放开给 Users 组。这会让所有用户都能替换系统级可执行文件是实打实的安全隐患。正确做法是只给特定应用数据目录授权而且优先改ProgramData下的目录别动Program Files。6.2 迁移或重装之后配置失灵这类问题可以归成一张排查顺序表我按命中率排的序现象优先检查原因类型改了配置不生效服务/快捷方式的工作目录路径指向别处启动就报找不到文件配置里的绝对路径硬编码路径命令版本不对PATH顺序环境变量卸载时报找不到安装源C:\Windows\Installer缓存被清新装的依赖找不到%APPDATA%下的缓存清单缓存未刷新第三条经验是凡是配置文件里写绝对路径的地方迁移前先全文搜一遍盘符。搜C:\和D:\这两个模式比逐行读靠谱得多。我处理过一台机器迁移后 Node 构建全挂原因就是某个工具的配置文件里写死了旧用户名的路径。6.3 清理 C 盘的顺序与禁区给一个我实际用的清理顺序从安全到激进用户级临时目录%TEMP%、%LOCALAPPDATA%\Temp。关掉所有程序再清。系统更新缓存设置里的存储感知或磁盘清理工具勾选Windows 更新清理。组件存储清理DISM /Online /Cleanup-Image /StartComponentCleanup。各种 IDE 与包管理器的缓存目录逐个确认后清。大目录迁移到其他盘 Junction。禁区清单也得有C:\Windows\Installer、C:\Windows\WinSxS、C:\Windows\System32、C:\Windows\Fonts、System Volume Information、C:\Windows\INF。这几处手删的收益远小于修复成本我见过因为清Installer导致 Office 无法卸载、只能重装的案例省了 2G 空间赔了一下午。6.4 中文用户名与空格路径引发的构建失败最后说一个和目录结构强相关、又特别隐蔽的问题。如果 Windows 账号是中文名用户目录就是C:\Users\张三。大量构建工具、脚本语言、老式编译器对非 ASCII 路径支持不好表现为编译报错、依赖安装失败、插件加载异常而且报错信息通常完全不提路径。同样的锅还有空格。C:\Program Files里的空格会打断没加引号的命令行参数C:\Users\Zhang San里的空格更狠很多脚本会把它切成两段。有效的规避方式有几条按推荐度排新建一个纯英文无空格的本地账号用于开发把项目放在D:\dev\这类浅路径下配置工具时使用程序数据目录而不是用户目录比如把包管理器缓存重定向到D:\cache\命令行里所有路径一律用双引号包裹。这不是洁癖是替未来的自己省时间——我在自己的开发机上始终保留一个纯英文账号装任何工具链之前都先切过去踩坑率能低一大截。关于目录结构本身我个人最受用的一条习惯是装任何软件之前先想一下它的三个落点——程序体在哪、配置在哪、数据在哪。脑子里有这张图出问题时排查路径是清晰的没有这张图就只能在重装试试里循环。真遇到拿不准的情况就用前面那招按修改时间排序抓写入文件比任何猜测都快。再补一个小技巧给C:\ProgramData和%LOCALAPPDATA%建个快捷方式放到桌面只放快捷方式不要移动目录平时多看一眼这两个地方的体积变化磁盘告急一般都能提前半个月发现而不是等到系统弹红条。