Hotdry.

Article

Windows TMP/TEMP 双环境变量: DOS 兼容性的技术考古与工程实践

从 CP/M 到 DOS 2.0 再到现代 Windows,分析 TMP 与 TEMP 双环境变量的历史渊源、程序优先级差异以及当前系统默认行为,为开发者提供兼容性与路径配置的实际指导。

2026-05-02systems

如果你在 Windows 系统中打开环境变量查看器,可能会注意到两个看似重复的变量:TMP 和 TEMP。它们都声称指向临时文件夹,但为什么要同时存在?如果两者不一致,哪个才是正确的?这些问题看似简单,却隐藏着一段跨越四十年的操作系统兼容性演进史。

从 CP/M 到 DOS:环境变量的诞生

要理解 TMP 和 TEMP 的起源,需要把时间拨回到一九七三年。彼时,个人计算机领域的主流操作系统是 CP/M(Control Program for Microcomputers)。值得注意的是,CP/M 本身并不支持环境变量 —— 这个概念在当时根本不存在。如果程序员想让程序知道临时文件应该存放在哪里,通常需要通过修补可执行文件中的特定字节来实现,例如调整驱动器字母。这种原始的配置方式在 WordStar 等经典软件中非常常见,用户手册甚至会详细列出需要修改的字节位置。

一九八一年,Intel 8086 处理器和 MS-DOS 操作系统的出现改变了一切。从架构设计角度看,8086 处理器和 MS-DOS 都深受 CP/M 的影响,其核心设计目标之一就是实现从 CP/M 程序到 MS-DOS 程序的机器翻译可行性。这种兼容性需求深刻影响了后续的许多技术决策,环境变量便是其中之一。

MS-DOS 在 CP/M 的基础上引入了环境变量这一机制。由于第一批 MS-DOS 程序大多是从 CP/M 移植过来的,这些程序原本并不使用环境变量,因此早期的 DOS 环境中虽然可以设置 TEMP 或 TMP 变量,但几乎没有任何程序会理睬它们。随着时间推移,越来越多的程序开始将环境变量作为配置数据的存储方式,于是两个用于指定临时文件位置的环境变量 ——TEMP 和 TMP—— 逐渐浮出水面,成为事实上的标准。

DOS 2.0 管道机制与 TEMP 的正式登场

MS-DOS 2.0 引入了一个关键特性:管道(piping)。由于 DOS 是单任务操作系统,管道的实现方式是将第一个程序的输出重定向到一个临时文件,运行完成后,再将第二个程序的输入从该临时文件重定向过来。这就要求操作系统必须知道在哪里创建这些临时文件。

正是在这个历史节点上,MS-DOS 的设计者选择了 TEMP 作为控制临时文件位置的变量。COMMAND.COM 在执行管道操作时会读取 TEMP 环境变量来确定临时文件的存储目录。然而,COMMAND.COM 选择了 TEMP 并不意味着其他程序也必须遵循这一约定。不同程序的作者根据各自的偏好,有的使用 TEMP,有的使用 TMP,还有的程序试图同时兼容两者,通过依次检查两个变量来确定最终使用的目录。例如,经典的 DISKCOPY 和 EDIT 程序会优先查找 TEMP,如果未找到则回退到 TMP。

Windows 的选择:GetTempFileName 函数的偏好

当 Windows 操作系统出现后,类似的兼容性博弈再次上演。Windows 提供了一个名为 GetTempFileName 的核心函数,用于生成唯一的临时文件名。鲜为人知的是,这个函数的实现选择了 TMP 作为第一优先级,优先于 TEMP。这意味着调用该函数的 Windows 程序会首先查找 TMP 环境变量,只有当 TMP 未定义时才会回退到 TEMP。

这种差异化设计导致了一个有趣的现象:不同的程序可能根据其开发时所依据的标准,选择使用不同的环境变量。Windows 原生程序通常通过 GetTempFileName 创建临时文件,因此更倾向于使用 TMP;而一些继承自 DOS 时代或为保持最大兼容性而设计的程序则可能优先使用 TEMP。这种双轨并存的局面一直延续至今,形成了 Windows 系统中独特的 “双变量” 现象。

现代 Windows 的默认行为与配置

在当前的 Windows 10 和 Windows 11 系统中,TMP 和 TEMP 默认情况下通常指向同一个位置:用户目录下的 AppData\Local\Temp 文件夹。以用户名为 alex 为例,默认路径通常是 C:\Users\alex\AppData\Local\Temp。系统在初始化这两个环境变量时,会进行一系列回退检查:首先尝试使用用户配置文件中定义的位置,如果未设置则使用系统默认值,最终确保两个变量都能指向一个有效的临时目录。

虽然大多数情况下两个变量指向同一位置,但在某些特殊场景下可能会出现差异。例如,某些企业环境中的系统策略可能只修改其中一个变量;部分 legacy 应用程序可能在启动时动态修改其中一个变量的值;或者用户手动编辑环境变量时只修改了其中一个。因此,在进行故障排查或性能优化时,同时检查这两个变量的值仍然是必要的操作。

对于希望将临时文件迁移到其他位置(如 RAM 磁盘或 SSD 分区)的用户,建议同时修改 TMP 和 TEMP 两个变量,以确保所有类型的程序都能遵循统一的配置。修改方法是打开系统属性中的环境变量设置界面,在用户变量区域找到 TEMP 和 TMP 条目,将它们设置为相同的自定义路径。需要注意的是,修改后需要重启正在运行的应用程序或重新登录会话,才能使新配置生效。

工程实践中的兼容性建议

从软件工程的角度来看,处理 TMP 和 TEMP 变量的最佳实践是采用双重检查策略。程序在需要获取临时文件目录时,应该同时查询 TMP 和 TEMP 两个变量,并根据预定义的优先级进行选择。参考 Windows API 的行为,建议优先检查 TMP,这与 GetTempFileName 函数的默认行为保持一致。如果 TMP 未定义,则回退到 TEMP。如果两者都未定义,则使用系统默认的临时目录。

对于需要在不同 Windows 版本间保持一致行为的脚本和部署工具,建议显式设置环境变量而不是依赖系统默认值。通过在脚本开头添加对 TMP 和 TEMP 的显式赋值,可以避免因不同系统配置导致的临时文件路径不一致问题。这种做法在构建系统、自动化部署和持续集成环境中尤为重要。

从技术考古的视角审视,TMP 和 TEMP 双变量并存的现象是操作系统兼容性演进的活化石。它见证了从 CP/M 到 DOS 再到 Windows 的完整技术迭代,承载了不同年代程序员的设计决策,并在现代系统中继续发挥着不可替代的作用。理解这一历史背景,不仅有助于解决实际的兼容性问题,更能让我们深刻体会到操作系统设计中向后兼容性所蕴含的复杂性和持久影响。

资料来源:Raymond Chen 在 Microsoft DevBlogs 发表的经典文章《Why are there both TMP and TEMP environment variables, and which one is right?》(2015 年 4 月 17 日)

systems