许多程序员在运行 DOS 的 PC 上学习了脚本编程。即使是功能受限的 DOS 批处理文件语言也允许编写相当强大的脚本和应用程序,尽管它们通常需要大量的变通方法和技巧。有时,仍然需要将旧的 DOS 批处理文件转换为 UNIX shell 脚本。这通常并不困难,因为 DOS 批处理文件操作符只是等效 shell 脚本操作符的一个有限子集。
表 N-1. 批处理文件关键字/变量/操作符及其 shell 等效项
| 批处理文件操作符 | Shell 脚本等效项 | 含义 |
|---|---|---|
| % | $ | 命令行参数前缀 |
| / | - | 命令选项标志 |
| \ | / | 目录路径分隔符 |
| == | = | (等于)字符串比较测试 |
| !==! | != | (不等于)字符串比较测试 |
| | | | | 管道 |
| @ | set+v | 不回显当前命令 |
| * | * | 文件名 “通配符” |
| > | > | 文件重定向(覆盖) |
| >> | >> | 文件重定向(追加) |
| < | < | 重定向标准输入 |
| %VAR% | $VAR | 环境变量 |
| REM | # | 注释 |
| NOT | ! | 否定后续测试 |
| NUL | /dev/null | 用于埋藏命令输出的 “黑洞” |
| ECHO | echo | echo(Bash 中有更多选项) |
| ECHO. | echo | echo 空行 |
| ECHO OFF | set+v | 不回显后续命令 |
| FOR %%VAR IN (LIST) DO | for var in [list]; do | “for” 循环 |
| :LABEL | 无(不必要) | 标签 |
| GOTO | 无(使用函数) | 跳转到脚本中的另一个位置 |
| PAUSE | sleep | 暂停或等待一段时间 |
| CHOICE | case 或 select | 菜单选择 |
| IF | if | if 测试 |
| IF EXISTFILENAME | if [ -e filename ] | 测试文件是否存在 |
| IF !%N==! | if [ -z "$N" ] | 如果可替换参数 “N” 不存在 |
| CALL | source 或 .(点操作符) | “包含” 另一个脚本 |
| COMMAND /C | source 或 .(点操作符) | “包含” 另一个脚本(与 CALL 相同) |
| SET | export | 设置环境变量 |
| SHIFT | shift | 左移命令行参数列表 |
| SGN | -lt 或 -gt | 符号(整数的) |
| ERRORLEVEL | $? | 退出状态 |
| CON | 标准输入 | “控制台” (标准输入) |
| PRN | /dev/lp0 | (通用)打印机设备 |
| LPT1 | /dev/lp0 | 第一个打印机设备 |
| COM1 | /dev/ttyS0 | 第一个串行端口 |
批处理文件通常包含 DOS 命令。为了将批处理文件转换为 shell 脚本,必须将这些命令转换为其 UNIX 等效项。
表 N-2. DOS 命令及其 UNIX 等效项
| DOS 命令 | UNIX 等效项 | 效果 |
|---|---|---|
| ASSIGN | ln | 链接文件或目录 |
| ATTRIB | chmod | 更改文件权限 |
| CD | cd | 更改目录 |
| CHDIR | cd | 更改目录 |
| CLS | clear | 清屏 |
| COMP | diff, comm, cmp | 文件比较 |
| COPY | cp | 文件复制 |
| Ctl-C | Ctl-C | 中断(信号) |
| Ctl-Z | Ctl-D | EOF(文件结束符) |
| DEL | rm | 删除文件 |
| DELTREE | rm -rf | 递归删除目录 |
| DIR | ls -l | 目录列表 |
| ERASE | rm | 删除文件 |
| EXIT | exit | 退出当前进程 |
| FC | comm, cmp | 文件比较 |
| FIND | grep | 在文件中查找字符串 |
| MD | mkdir | 创建目录 |
| MKDIR | mkdir | 创建目录 |
| MORE | more | 文本文件分页过滤器 |
| MOVE | mv | 移动 |
| PATH | $PATH | 可执行文件路径 |
| REN | mv | rename(移动) |
| RENAME | mv | rename(移动) |
| RD | rmdir | 删除目录 |
| RMDIR | rmdir | 删除目录 |
| SORT | sort | 排序文件 |
| TIME | date | 显示系统时间 |
| TYPE | cat | 输出文件到标准输出 |
| XCOPY | cp | (扩展)文件复制 |
![]() | 实际上,所有 UNIX 和 shell 操作符和命令都比其 DOS 和批处理文件对应项具有更多的选项和增强功能。许多 DOS 批处理文件依赖于辅助实用程序,例如 ask.com,它是 read 的功能受限的对应物。 DOS 仅支持文件名 通配符展开 的非常有限且不兼容的子集,仅识别 * 和 ? 字符。 |
将 DOS 批处理文件转换为 shell 脚本通常很简单,并且结果通常比原始文件更易读。
示例 N-1. VIEWDATA.BAT:DOS 批处理文件
REM VIEWDATA REM INSPIRED BY AN EXAMPLE IN "DOS POWERTOOLS" REM BY PAUL SOMERSON @ECHO OFF IF !%1==! GOTO VIEWDATA REM IF NO COMMAND-LINE ARG... FIND "%1" C:\BOZO\BOOKLIST.TXT GOTO EXIT0 REM PRINT LINE WITH STRING MATCH, THEN EXIT. :VIEWDATA TYPE C:\BOZO\BOOKLIST.TXT | MORE REM SHOW ENTIRE FILE, 1 PAGE AT A TIME. :EXIT0 |
脚本转换在某种程度上有所改进。[1]
示例 N-2. viewdata.sh:VIEWDATA.BAT 的 Shell 脚本转换
#!/bin/bash # viewdata.sh # Conversion of VIEWDATA.BAT to shell script. DATAFILE=/home/bozo/datafiles/book-collection.data ARGNO=1 # @ECHO OFF Command unnecessary here. if [ $# -lt "$ARGNO" ] # IF !%1==! GOTO VIEWDATA then less $DATAFILE # TYPE C:\MYDIR\BOOKLIST.TXT | MORE else grep "$1" $DATAFILE # FIND "%1" C:\MYDIR\BOOKLIST.TXT fi exit 0 # :EXIT0 # GOTOs, labels, smoke-and-mirrors, and flimflam unnecessary. # The converted script is short, sweet, and clean, #+ which is more than can be said for the original. |
Ted Davis 的 PC 上的 Shell 脚本 站点有一套关于老式批处理文件编程艺术的综合教程。不幸的是,该页面已消失得无影无踪。
| [1] | 各种读者建议对上述批处理文件进行修改,使其更美观、更紧凑和更高效。ABS 指南 的作者认为,这是徒劳的。Bash 脚本可以访问 DOS 文件系统,甚至 NTFS 分区(借助 ntfs-3g)来执行批处理或脚本操作。 |