許多從 DOS/Windows 轉戰 Linux/Unix 的開發者,手邊常有舊有的 .bat 批次檔需要移植。好消息是:DOS 批次語法其實只是 Shell 腳本功能的子集,轉換通常不難,且轉換後的腳本往往更簡潔、強健。本文提供關鍵字、運算子、常用命令的完整對照表,並以實際範例示範轉換流程。
核心語法對照表
| DOS 批次檔 | Shell 腳本 | 說明 |
% | $ | 命令列參數前綴 |
/ | - | 選項標記 |
\ | / | 路徑分隔符 |
== | = | 字串比較(相等) |
!= | != | 字串比較(不等) |
| | | | 管線 |
@ | set +v | 不顯示當前命令 |
* | * | 檔名萬用字元 |
> | > | 輸出重導向(覆蓋) |
>> | >> | 輸出重導向(附加) |
< | < | 輸入重導向 |
%VAR% | $VAR | 環境變數 |
REM | # | 註解 |
NOT | ! | 邏輯否定 |
NUL | /dev/null | 丟棄輸出的黑洞裝置 |
ECHO | echo | 列印(Bash 選項更豐富) |
ECHO. | echo | 列印空行 |
ECHO OFF | set +v | 關閉命令回顯 |
FOR %%V IN (L) DO | for v in list; do | for 迴圈 |
:LABEL | 無對應 | 標籤(Shell 用函數取代) |
GOTO | 無對應 | 跳轉(Shell 用函數/流程控制) |
PAUSE | read 或 sleep | 暫停/等待 |
CHOICE | case 或 select | 選單選擇 |
IF | if | 條件判斷 |
IF EXIST FILE | if [ -e file ] | 檢測檔案存在 |
IF !%N==! | if [ -z "$N" ] | 檢測參數是否為空 |
CALL | source 或 . | 引入另一腳本 |
COMMAND /C | source 或 . | 同 CALL |
SET | export | 設定環境變數 |
SHIFT | shift | 左移參數列表 |
ERRORLEVEL | $? | 上一指令結束碼 |
CON | stdin | 主控台輸入 |
PRN | /dev/lp0 | 列印裝置 |
LPT1 | /dev/lp0 | 第一列印裝置 |
COM1 | /dev/ttyS0 | 第一序列埠 |
常用 DOS 命令對應 UNIX 命令
| DOS 命令 | UNIX 對應 | 功能 |
| ASSIGN | ln | 連結檔案/目錄 |
| ATTRIB | chmod | 修改權限 |
| CD / CHDIR | cd | 切換目錄 |
| CLS | clear | 清除螢幕 |
| COMP | diff, comm, cmp | 檔案比較 |
| COPY | cp | 複製檔案 |
| DEL / ERASE | rm | 刪除檔案 |
| DELTREE | rm -rf | 遞迴刪除目錄 |
| DIR | ls -l | 列出目錄內容 |
| EXIT | exit | 離開程序 |
| FIND | grep | 檔案內搜尋字串 |
| MD / MKDIR | mkdir | 建立目錄 |
| MORE | more / less | 分頁顯示 |
| MOVE | mv | 移動/重新命名 |
| PATH | $PATH | 執行檔搜尋路徑 |
| REN / RENAME | mv | 重新命名 |
| RD / RMDIR | rmdir | 刪除空目錄 |
| SORT | sort | 排序 |
| TIME | date | 顯示系統時間 |
| TYPE | cat | 輸出檔案到 stdout |
| XCOPY | cp -r | 擴展複製 |
實戰範例:VIEWDATA.BAT → viewdata.sh
原始 DOS 批次檔
REM VIEWDATA
@ECHO OFF
IF !%1==! GOTO VIEWDATA
FIND "%1" C:\BOZO\BOOKLIST.TXT
GOTO EXIT0
:VIEWDATA
TYPE C:\BOZO\BOOKLIST.TXT | MORE
:EXIT0
轉換後的 Shell 腳本
#!/bin/bash
# viewdata.sh - 由 VIEWDATA.BAT 轉換而來
DATAFILE=/home/bozo/datafiles/book-collection.data
ARGNO=1
if [ $# -lt "$ARGNO" ]; then
less "$DATAFILE" # 對應 TYPE ... | MORE
else
grep "$1" "$DATAFILE" # 對應 FIND "%1" ...
fi
exit 0
# 無需 GOTO、標籤,結構更清晰
改進重點
- 移除
@ECHO OFF,Shell 預設不回顯命令。
- 用
$# 判斷參數個數,取代 IF !%1==!。
- 以
if/else 取代 GOTO,邏輯線性易讀。
TYPE | MORE 改用 less(支援上下翻頁、搜尋)。
FIND 改用 grep(正則表達式、大小寫忽略等進階功能)。
- 路徑改用 Unix 風格,並建議將資料檔放在
$HOME 下。
轉換提示
- 逐行對照:先建立對照表,再機械式替換關鍵字與命令。
- 重構流程:將
GOTO 導向的標籤改寫為函數或 if/elif/else 結構。
- 善用 Shell 特性:陣列、關聯陣列、進階參數展開、命令替換
$(...)、管線串接,往往能將數十行批次檔壓縮為幾行。
- 測試驗證:在類 Unix 環境(Git Bash、WSL、Linux VM)逐步執行,對照原輸出。
參考資源:Ted Davis 的 Shell Scripts on the PC 網站收錄大量批次檔技巧,許多發想與 Shell 腳本異曲同工。