【Windows 批处理乱码问题:BAT 编码和 CMD 代码页真的会坑你】
Windows 批处理乱码问题BAT 编码和 CMD 代码页真的会坑你最近写了一个 Windows 批处理脚本用来把一个目录里的内容备份到另一个硬盘目录里。脚本本身不复杂核心就是robocopy。为了用起来方便我加了一些中文提示比如让用户输入源目录、目标目录再选择复制模式。一开始我以为这只是一个很普通的.bat脚本结果运行后直接翻车。CMD 里出现了类似这样的报错目录例如 is not recognized as an internal or external command, operable program or batch file.刚看到这个错误的时候有点懵。因为它不是单纯的中文显示乱码而是 CMD 把乱码内容当成命令去执行了。也就是说脚本已经不是“看起来乱码”这么简单而是被错误解析了。问题现象原来的脚本大概是这样echo off chcp 65001 nul title 目录复制 / 备份工具 echo echo Windows 目录复制工具 echo echo. set /p SRC请输入源目录例如 G:\ 或 D:\a set /p DST请输入目标目录例如 H:\ 或 E:\b看起来没什么问题。但是运行时中文提示被 CMD 解析坏了甚至出现了类似这样的报错目录例如 is not recognized as an internal or external command这就说明问题不只是显示层面的乱码而是脚本内容在执行阶段就已经被 CMD 误读了。根本原因文件编码和 CMD 代码页不匹配后来排查下来问题主要出在两个地方1. .bat 文件本身是什么编码 2. CMD 当前使用的是什么代码页.bat文件本质上就是一个文本文件。我们看到的是请输入源目录但对 CMD 来说它读取的是一串字节。如果这个文件是 UTF-8 保存的而 CMD 按 GBK 去理解就可能乱码。反过来如果文件是 ANSI / GBK 保存的而 CMD 被切到了 UTF-8也可能乱码。所以这类问题的关键不是“中文能不能显示”而是BAT 文件编码和 CMD 代码页必须对得上。只要对不上就容易出现各种奇怪问题。先看 CMD 当前代码页在 CMD 里可以用这个命令查看当前代码页chcp比如我这里看到的是Active code page: 936常见几个代码页大概是代码页含义936简体中文 GBK / ANSI65001UTF-8437英文美国950繁体中文 Big5在中文 Windows 环境下936是比较传统也比较稳的选择。我的解决方式最后我是这样处理的1. 把 .bat 文件编码改成 ASCII / ANSI 兼容格式 2. 在 CMD 里用 chcp 查看当前代码页 3. 在脚本开头写 chcp 936 nul脚本开头改成echo off chcp 936 nul title 目录复制 / 备份工具这里的chcp 936意思是把当前 CMD 会话切到简体中文 GBK 代码页。后面的nul是为了把输出隐藏掉。否则它会多打印一行Active code page: 936加上nul之后脚本界面会干净一些。文件编码怎么改我这次是把 BAT 脚本改成了 ASCII / ANSI 兼容格式。如果你用的是 VS Code可以看右下角的编码显示点击之后选择Save with Encoding然后保存成适合当前环境的编码。如果用 Notepad可以在顶部菜单里找到编码然后选择转成 ANSI 或 GBK 相关编码。如果用 Windows 记事本也可以文件 另存为在底部选择编码。对于中文 Windows 下的 CMD 批处理我个人更倾向于ANSI / GBK chcp 936这套组合比较朴素但稳定。顺手改一下set /p的写法这次还顺便改了一个批处理里的细节。原来写法是set /p SRC请输入源目录例如 G:\ 或 D:\a现在改成set /p SRC请输入源目录例如 G:\ 或 D:\a目标目录也是一样set /p DST请输入目标目录例如 H:\ 或 E:\b这个写法更稳。因为批处理对空格、特殊字符、中文标点都比较敏感。把整个变量提示内容用双引号包起来可以减少解析出问题的概率。路径也一定要加引号如果路径里有中文或者空格命令里也要加引号。比如robocopy %SRC% %DST% /E不要写成robocopy %SRC% %DST% /E否则遇到这种路径就容易出问题D:\软件包 H:\软件包\编程 D:\Program Files\Test尤其是带空格的路径不加引号基本必炸。为什么这次不用chcp 65001一开始我用了chcp 65001 nul也就是 UTF-8。理论上 UTF-8 更通用也更现代但在 Windows 的传统 CMD 和.bat脚本里UTF-8 并不总是省心。它可能受这些因素影响1. BAT 文件是不是 UTF-8 with BOM 2. 当前控制台字体是否支持中文 3. 某些老命令对 UTF-8 支持是否完整 4. 中文符号有没有被正确解析所以如果只是写给中文 Windows CMD 使用我现在更愿意用chcp 936 nul简单直接少折腾。最后稳定下来的脚本开头现在我的 BAT 文件开头基本会这样写echo off chcp 936 nul title 目录复制 / 备份工具 echo echo Windows 目录复制工具 echo echo.交互输入这样写set /p SRC请输入源目录例如 G:\ 或 D:\a set /p DST请输入目标目录例如 H:\ 或 E:\b执行命令时路径变量统一加引号robocopy %SRC% %DST% /E总结这次问题看起来是“中文乱码”但本质上是BAT 文件编码和 CMD 当前代码页不匹配。我的最终处理方式是BAT 文件保存为 ASCII / ANSI 兼容格式 脚本开头使用 chcp 936 nul 输入语句用 set /p 变量提示内容 路径变量在命令里全部加双引号改完之后中文提示正常了中文路径也能正常输入脚本执行也没有再出现乱码命令的问题。这类问题不算难但很容易被忽略。尤其是现在很多编辑器默认保存 UTF-8而 Windows CMD 的历史包袱又比较重两个东西一碰上就可能出现这种莫名其妙的乱码报错。