附录 N. 将 DOS 批处理文件转换为 Shell 脚本

许多程序员在运行 DOS 的 PC 上学习了脚本编程。即使是功能受限的 DOS 批处理文件语言也允许编写相当强大的脚本和应用程序,尽管它们通常需要大量的变通方法和技巧。有时,仍然需要将旧的 DOS 批处理文件转换为 UNIX shell 脚本。这通常并不困难,因为 DOS 批处理文件操作符只是等效 shell 脚本操作符的一个有限子集。

表 N-1. 批处理文件关键字/变量/操作符及其 shell 等效项

批处理文件操作符Shell 脚本等效项含义
%$命令行参数前缀
/-命令选项标志
\/目录路径分隔符
===(等于)字符串比较测试
!==!!=(不等于)字符串比较测试
||管道
@set+v不回显当前命令
**文件名 “通配符”
>>文件重定向(覆盖)
>>>>文件重定向(追加)
<<重定向标准输入
%VAR%$VAR环境变量
REM#注释
NOT!否定后续测试
NUL/dev/null用于埋藏命令输出的 “黑洞”
ECHOechoecho(Bash 中有更多选项)
ECHO.echoecho 空行
ECHO OFFset+v不回显后续命令
FOR %%VAR IN (LIST) DOfor var in [list]; do“for” 循环
:LABEL无(不必要)标签
GOTO无(使用函数)跳转到脚本中的另一个位置
PAUSEsleep暂停或等待一段时间
CHOICEcase 或 select菜单选择
IFifif 测试
IF EXISTFILENAMEif [ -e filename ]测试文件是否存在
IF !%N==!if [ -z "$N" ]如果可替换参数 “N” 不存在
CALLsource 或 .(点操作符)“包含” 另一个脚本
COMMAND /Csource 或 .(点操作符)“包含” 另一个脚本(与 CALL 相同)
SETexport设置环境变量
SHIFTshift左移命令行参数列表
SGN-lt 或 -gt符号(整数的)
ERRORLEVEL$?退出状态
CON标准输入“控制台” (标准输入)
PRN/dev/lp0(通用)打印机设备
LPT1/dev/lp0第一个打印机设备
COM1/dev/ttyS0第一个串行端口

批处理文件通常包含 DOS 命令。为了将批处理文件转换为 shell 脚本,必须将这些命令转换为其 UNIX 等效项。

表 N-2. DOS 命令及其 UNIX 等效项

DOS 命令UNIX 等效项效果
ASSIGNln链接文件或目录
ATTRIBchmod更改文件权限
CDcd更改目录
CHDIRcd更改目录
CLSclear清屏
COMPdiff, comm, cmp文件比较
COPYcp文件复制
Ctl-CCtl-C中断(信号)
Ctl-ZCtl-DEOF(文件结束符)
DELrm删除文件
DELTREErm -rf递归删除目录
DIRls -l目录列表
ERASErm删除文件
EXITexit退出当前进程
FCcomm, cmp文件比较
FINDgrep在文件中查找字符串
MDmkdir创建目录
MKDIRmkdir创建目录
MOREmore文本文件分页过滤器
MOVEmv移动
PATH$PATH可执行文件路径
RENmvrename(移动)
RENAMEmvrename(移动)
RDrmdir删除目录
RMDIRrmdir删除目录
SORTsort排序文件
TIMEdate显示系统时间
TYPEcat输出文件到标准输出
XCOPYcp(扩展)文件复制

Note

实际上,所有 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)来执行批处理或脚本操作。