將DOS批處理檔案轉換為Shell指令碼

一劍平江湖發表於2017-06-16

相當多的在PC上學習指令碼的程式設計師都在執行DOS. 事實上, 殘廢的DOS批處理檔案語言還是可以編寫出一些比較強大的指令碼來的, 雖然它們一般都需要藉助於外部的工具. 所以說, 某些時候, 我們還是需要將老式的DOS批處理檔案轉換為UNIX shell指令碼. 一般來說, 做這種事情並不困難, 因為DOS批處理檔案操作不過是等價的shell指令碼的一個受限子集.


表格 L-1. 批處理檔案關鍵字 / 變數 / 操作符, 和等價的shell符號

批處理檔案操作符 Shell指令碼等價符號 含義
% $ 命令列引數字首
/ - 命令選項標記
\ / 目錄路徑分隔符
== = (等於)字串比較測試
!==! != (不等)字串比較測試
| | 管道
@ set +v 不列印當前命令
* * 檔名"萬用字元"
> > 檔案重定向(覆蓋)
>> >> 檔案重定向(附加)
< < 重定向stdin
%VAR% $VAR 環境變數
REM # 註釋
NOT ! 取反
NUL /dev/null "黑洞"用來阻止命令輸出
ECHO echo 列印(Bash中有更多選項)
ECHO. echo 列印空行
ECHO OFF set +v 不列印後續的命令
FOR %%VAR IN (LIST) DO for var in [list]; do "for"迴圈
:LABEL 沒有等價物(多餘) 標籤
GOTO 沒有等價物(使用函式) 跳轉到指令碼的另一個位置
PAUSE sleep 暫停或等待一段時間
CHOICE case or select 選單選擇
IF if if條件語句
IF EXIST FILENAME if [ -e filename ] 測試檔案是否存在
IF !%N==! if [ -z "$N" ] 引數"N"是否存在
CALL source命令或.(點操作符) "include"另一個指令碼
COMMAND /C source命令或.(點操作符) "include"另一個指令碼(與CALL相同)
SET export 設定一個環境變數
SHIFT shift 左移命令列引數列表
SGN -lt或-gt (整形)符號
ERRORLEVEL $? 退出狀態
CON stdin "控制檯"(stdin)
PRN /dev/lp0 (一般的)列印裝置
LPT1 /dev/lp0 第一個列印裝置
COM1 /dev/ttyS0 第一個串列埠

批處理檔案一般都包含DOS命令. 我們必須把它轉換為UNIX的等價命令, 這樣我們才能把批處理檔案轉換為shell指令碼檔案. 


表格 L-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 mv 重新命名(移動)
RD rmdir 刪除目錄
RMDIR rmdir 刪除目錄
SORT sort 排序檔案
TIME date 顯示系統時間
TYPE cat 將檔案輸出到stdout
XCOPY cp (擴充套件的)檔案拷貝

 

事實上, 幾乎所有的UNIX和shell操作符, 還有命令都有許多的選項, 對比DOS和批處理檔案來說, 它們要強大的多. 許多DOS批處理檔案都需要依靠輔助工具, 比如ask.com, 這是一個比read命令差很多的類似副本.

DOS對於檔名萬用字元擴充套件支援的非常有限, 並且很不完整, 僅僅識別*?.

將DOS批處理檔案轉換為sehll指令碼, 通常是一件很簡單的事情, 而且轉換的結果通常都比原始的批處理檔案好. 


例子 L-1. VIEWDATA.BAT: DOS批處理檔案

1 REM VIEWDATA
  2 
  3 REM 靈感來自於例子"DOS POWERTOOLS"
  4 REM                           PAUL SOMERSON編寫
  5 
  6 
  7 @ECHO OFF
  8 
  9 IF !%1==! GOTO VIEWDATA
 10 REM  如果沒有命令列引數...
 11 FIND "%1" C:\BOZO\BOOKLIST.TXT
 12 GOTO EXIT0
 13 REM  列印出字串匹配的行, 然後退出. 
 14 
 15 :VIEWDATA
 16 TYPE C:\BOZO\BOOKLIST.TXT | MORE
 17 REM  顯示整個檔案, 一次一頁. 
 18 
 19 :EXIT0

轉換指令碼作了一些改進. 


例子 L-2. viewdata.sh: 轉換自VIEWDATA.BAT的shell指令碼

1 #!/bin/bash
  2 # viewdata.sh
  3 # 轉換自VIEWDATA.BAT的shell指令碼. 
  4 
  5 DATAFILE=/home/bozo/datafiles/book-collection.data
  6 ARGNO=1
  7 
  8 # @ECHO OFF                 這個命令在這裡就不需要了. 
  9 
 10 if [ $# -lt "$ARGNO" ]    # IF !%1==! GOTO VIEWDATA
 11 then
 12   less $DATAFILE          # TYPE C:\MYDIR\BOOKLIST.TXT | MORE
 13 else
 14   grep "$1" $DATAFILE     # FIND "%1" C:\MYDIR\BOOKLIST.TXT
 15 fi  
 16 
 17 exit 0                    # :EXIT0
 18 
 19 #  跳轉, 標籤, 還有其他一些小手段, 在shell指令碼中就不需要了. 
 20 #  我們可以說, 轉換後的指令碼比原始批處理檔案好的多, 
 21 #+ 它更短, 看起來更整潔, 更優雅.

Ted Davis的Shell Scripts on the PC站點上有許多關於老式的批處理檔案程式設計的教程, 他使用的某些獨創性的技術, 和shell指令碼有異曲同工之妙.

相關文章