这条路径解决什么
老系统导出的文本常常是 GBK 或 GB18030,直接拿到 UTF-8 环境里会显示为乱码。稳妥的处理顺序是:先用 file -i 逐个探测实际编码,再用 iconv 转换并写入临时文件,成功后替换原文件,接着统一行尾,最后抽样复核中文与行数。整个流程可重复、可回溯,避免直接覆盖造成不可逆的乱码。
基本信息
| 适用场景 | 旧编码文本批量转 UTF-8,或做编码规范化 |
|---|---|
| 核心工具 | file -i 探测、iconv 转换、dos2unix 统一行尾 |
| 必做前置 | 整目录备份,例如 cp -a data data.bak |
| 转换策略 | 先写临时文件,转换成功再原子替换,避免失败留下半个文件 |
| 复核方式 | 随机抽样看中文,比对转换前后的行数与文件大小 |
典型使用场景
- 导入历史数据:老系统导出的 CSV 是 GBK,入库前统一成 UTF-8
- 站点升级:旧模板文件编码不一,统一后才能正确显示与检索
- 日志分析:日志里混入非 UTF-8 字节导致 grep 或 jq 解析异常
- 跨平台交付:给不同平台准备编码一致的文件
- 排查乱码投诉:先确认文件本身的真实编码,再判断是浏览器还是终端的问题
探测与转换
探测与转换
file -i data/*.txt # 批量探测编码
iconv -f GB18030 -t UTF-8 export.csv > export.csv.utf8 # 先写临时文件
iconv -l | grep -i gb # 确认本机支持的目标编码名
for f in data/*.txt; do
iconv -f GB18030 -t UTF-8 "$f" > "$f.utf8" && mv "$f.utf8" "$f" # 成功才替换
done
file -i data/*.txt # 转换后复核统一行尾并复核
统一行尾并复核
find data -name '*.txt' -exec dos2unix -k {} +
wc -l data/*.txt > after.txt # 与转换前对比行数
head -n 3 data/export.csv # 抽样看中文是否正常探测结果读法
| file -i 输出 | 含义 | 处理 |
|---|---|---|
| us-ascii | 纯 ASCII,没有非英文字节 | 通常无需转换,但要确认是否真的是全英文 |
| utf-8 | 已经是 UTF-8 | 确认无 BOM 即可 |
| iso-8859-1 | 西欧单字节编码 | 多为探测猜测,实际可能是 GBK,需人工确认 |
| gb2312 或 gb18030 | 简体中文编码 | 用 iconv 转成 UTF-8 |
| utf-16le 或 utf-16be | 带 BOM 的宽字符 | 转换时注意 BOM 的处理 |
转换前先整目录备份(cp -a data data.bak),转换后抽查中文是否正常、行数是否与转换前一致。行数与字节数都对得上,乱码与截断这两类问题基本能排除。
iconv 加 -c 会静默丢弃无法转换的字节:命令成功返回,但内容已经缺字少句,事后极难发现。除非明确知道并接受这个后果,不要用 -c;遇到非法字节应先定位来源,再决定是修数据还是换编码名。
编码名要写对,否则 iconv 直接报 unsupported conversion 而不会猜:简体中文常见写法有 gb2312、gbk、gb18030 与 GB18030,用 iconv -l 可以列出本机支持的全部名称。批量转换前先拿一个文件试通,确认目标编码名可用再铺开。