批处理迁移为什么不能逐行翻译
Windows 批处理与 shell 的差异不只在语法:变量展开时机、错误处理模型、路径分隔符、编码与换行都不一样。逐行直译出来的脚本通常能跑通第一条命令,却在遇到空格路径、错误分支或中文输出时出错,因此结构简单的脚本重写一遍比翻译一遍更省时间。
迁移要连带处理的三件事
第一是换行与编码,从 Windows 拷来的文件常带回车换行和 GBK 编码,直接执行会报解释器错误或中文乱码;第二是错误处理,批处理用错误码变量判断,shell 用退出状态配合 set -e 与管道状态;第三是调度绑定,原计划任务要改写成 cron 或 systemd 定时单元,并同步修改日志路径。
基本信息
| 适用平台 | 从 Windows 迁移到 Linux、麒麟、UOS 等平台的脚本 |
|---|---|
| 首选解释器 | bash,避免使用仅 POSIX 子集外的写法时注明 |
| 静态检查 | bash -n 语法检查,shellcheck 风格检查 |
| 换行处理 | dos2unix 或 sed 去掉回车符 |
典型使用场景
- 机房巡检脚本从 Windows 批处理改写为 Linux 定时任务
- 文件分发与备份脚本迁移到信创服务器
- 老业务系统的启动脚本随应用一起搬到国产化平台
- 把依赖批处理拼接的报表流程改成可维护的 shell 脚本
- 迁移评估阶段快速估量待改造脚本的数量与复杂度
常见结构对照
常见结构对照
# 批处理:set /p name=输入名称
read -p '输入名称: ' name
# 批处理:if not exist dir mkdir dir
mkdir -p "$dir"
# 批处理:for %%f in (*.log) do echo %%f
for f in *.log; do echo "$f"; done
# 批处理:call :func 与 exit /b 0 的子过程写法
my_func() { echo "$1"; }
my_func hello转换后检查
转换后检查
file script.sh # 检查是否带 CRLF 与编码
sed -i 's/\r$//' script.sh # 去回车,等价于 dos2unix
bash -n script.sh # 语法检查
chmod +x script.sh # 赋执行权限
command -v shellcheck >/dev/null && shellcheck script.sh || true逐项替换清单
| 批处理写法 | shell 对应写法 | 注意点 |
|---|---|---|
| %VAR% | $VAR 或 ${VAR} | 赋值不能有空格,取值建议加引号 |
| set /a | $(( )) 算术展开 | 整数运算,浮点需用 bc |
| if errorlevel | $? 退出状态 | 管道只反映最后一条命令的状态 |
| \\ 路径分隔符 | / 路径分隔符 | 转换时统一替换,注意转义字符 |
| echo off 系列 | 无需对应 | 脚本内不要保留批处理专用指令 |
转换完成后同步检查调用方:计划任务、监控脚本与其他脚本里对原批处理的调用路径都要一并更新,否则会出现脚本本身可用但调度不到的情况。