BAT 批次檔

MS-DOS 與 Windows 作業系統,可以使用副檔名為 *.bat 的純文字文件格式,來編寫命令,讓系統執行工作。內容除了可以執行 DOS 命令外,還提供些許存取系統資料與邏輯控制等功能。在不方便使用 Java 或 C 語言來執行程式功能的場合,改用 BAT 批次檔來完成工作,不失為有效的解決方案。


輸出訊息

ECHO 訊息

用來輸出自己想要顯示出來的訊息。


隱藏指令執行時輸出的訊息

@

DOS 命令在執行時,會顯示過程中產生的訊息。如果不想看到這樣的訊息,可用 @ 表示這行程式不顯示過程訊息。


關閉指令執行時輸出的訊息

ECHO OFF

所有程式都不顯示過程訊息。

通常連 ECHO OFF 這行程式也不希望顯示過程訊息,因此會在前面加上 @,變成 @ECHO OFF。


輸出空行

@ECHO;


暫停

PAUSE

程式停止執行,等待使用者按任意鍵再繼續。

如果想自己另外用 ECHO 輸出訊息,忽略 PAUSE 的「請按任意鍵繼續」,可以將訊息導向 NUL:

PAUSE >NUL


暫停幾秒

TIMEOUT 秒數


尋訪

FOR %%變數 IN (篩選) DO 指令 [參數]

FOR 指令與其說是迴圈,不如說是用來尋訪檔案。變數保存的是尋訪的檔案名稱。

篩選的寫法像是 (*.mp4 *.mkv),沒有篩選條件的話用萬用字元 (*)。

底下範例會開啟批次檔所在資料夾下所有 *.txt 檔案:

FOR %%n IN (*.txt) DO %%n


跳躍

跳到特定位置,執行其後的程式。


設定跳躍點

:標題


跳躍

GOTO 標題


最常見的用法是設定 :end 做為批次檔的結尾,然後在批次檔已經完成任務時,就可以跳過接下來的程式,直接結束工作。


條件


檢查資料

IF %變數% == 資料

除了 ==,還有以下檢查方式:

neq不等於
lss小於
leq小於等於
gtr大於
geq大於等於

檢查資料夾或檔案是否存在

IF EXIST 資料夾或檔案


檢查批次檔接受到的數值資料

IF ERRORLEVEL 數值


反向條件

IF 後面可用 NOT 作相反條件的判斷。


分歧條件

IF 判斷式 (執行功能) ELSE (執行功能)

注意!ELSE 與前面的 ) 符號不能斷行!

也因此,為了讓批次檔的分歧條件式,能夠更像結構化程式語言的 if else,可以採用如下的編寫風格:

IF 判斷式 (
 執行功能
) ELSE (
 執行功能
)

甚至多數人覺得,在批次檔使用 GOTO,反而比 IF ELSE 容易閱讀。(不過 GOTO 比較不好寫,因為用「下一行」取代 ELSE 的情況下,要更花費心力,才能安排好執行流程。)


詢問

CHOICE

會詢問 Y/N。

其後應搭配 IF %ERRORLEVEL%==1 判斷使用者選的是 Y,或者 IF %ERRORLEVEL%==2 選的是 N。

CHOICE 還允許自定更多選項,例如:

CHOICE /C NESW /M "N=北 E=東 S=南 W=西"
IF %ERRORLEVEL%==1 ECHO 往北走了
IF %ERRORLEVEL%==2 ECHO 往東走了
IF %ERRORLEVEL%==3 ECHO 往南走了
IF %ERRORLEVEL%==4 ECHO 往西走了


輸入

SET /P 變數名稱=說明文字


參數

接在批次檔後面的參數,可用 %1%9 來取得。

帶入的 %1 參數是檔案的話,可以用如下修飾子處理路徑和檔名:

%~1不帶 "" 符號的 %1,可避免雙引號了雙引號的路徑
%~d1磁碟機代號
%~p1路徑
%~n1檔名
%~x1副檔名

這些可以寫在一起,比如 %~nx1 表示檔名和副檔名,%~dpn1 表示有完整路徑和檔名但不含副檔名。

如果 ~dp1 因為資料夾後面有個 \ 造成問題的話,可以寫 ~dp1. 用個 . 表示當前路徑。

這些修飾子,前後通常用 "" 包起來,以免發生路徑或檔名有空白的問題。

參數 %2 到參數 %9 依此類推,數字改成 2 到 9 而已。

批次檔本身的路徑,則用 %0 來表示,同樣能用上述的修飾子,只是數字改成 0,這在設計把檔案拖曳到批次檔的程式時用得到。

除了檔名,還有以下訊息可以取出:

%~z1檔案大小
%~t1修改時間

如果要帶入所有參數給另一個程式指令,可用 %*,比如:

@D:\Applications\Git\cmd\git.exe %*


變數

取一個識別名稱,保存程式中所要用到的資料,以便讀取。


設定變數

SET 變數名稱=資料


讀取變數

%變數名稱%
%變數名稱:~開始位置,擷取字數%

擷取字數可以用負號 - 表示從後面倒過來數。


系統環境變數

Windows 作業系統已經內定許多環境變數,可以方便我們設計批次檔時,更簡單、明確進行想要的操作目標:

%DATE%年/月/日 週數
%RANDOM%隨機取得 0 到 32767 之間的整數
%TIME%時:分:秒.毫秒

路徑:

%CD%當前路徑
%PROGRAMFILES%C:\Program Files
%PROGRAMFILES(X86)%C:\Program Files (x86)
%SYSTEMDRIVE%C:
%SYSTEMROOT%C:\WINDOWS

使用者:

%APPDATA%C:\Users\帳戶名稱\AppData\Roaming
%HOMEDRIVE%C:
%HOMEPATH%\Users\帳戶名稱
%LOCALAPPDATA%C:\Users\帳戶名稱\AppData\Local
%TEMP%C:\Users\帳戶名稱\AppData\Local\Temp
%USERNAME%帳戶名稱
%USERPROFILE%C:\Users\帳戶名稱

綜合範例

SET MONTH=%DATE:~5,2%
SET DAY=%DATE:~8,2%
tar -cf MyBackup-%MONTH%%DAY%.tar D:\MyBackup
@ECHO %TIME%
PAUSE


呼叫外部批次檔

CALL 批次檔

執行另一個批次檔,然後繼續往下一個流程執行。


結束正在執行的程式

TASKKILL /IM 程序名稱
TASKKILL /PID 處理程序識別碼


結束批次檔

EXIT


一行內執行多道指令

使用 & 符號。


多行指令寫成一道指令

() 符號括住。


註解

REM 註解文字

不會被批次檔執行,適合用來說明程式意圖,方便往後閱讀程式碼。

通常前面會加上 @ 符號,以免畫面顯示這段註解文字。


配色

COLOR 背景顏色和前景顏色

0 黑色
1 藍色
2 綠色
3 藍綠色
4 紅色
5 紫色
6 黃色
7 淺灰色
8 深灰色
9 淡藍色
A 淡綠色
B 淡藍綠色
C 淡紅色
D 淡紫色
E 淡黃色
F 白色

兩個顏色要連在一起,例如白色背景和藍色文字:

COLOR F1


視窗大小

MODE CON COLS=寬度 LINES=高度

單位分別是字元數和行數,不是像素。


視窗標題

TITLE 文字


免命令提示字元視窗執行應用程式

點兩下批次檔,是可以不帶命令提示字元視窗,只啟動應用程式的:

START 應用程式

少數應用程式,需要依賴開始位置,才能正常載入其他檔案,這時就要用:

START /D 路徑 應用程式

使用 START 要注意,它遇到第一個 "" 的參數,會視為「設定視窗標題文字」,所以要執行的應用程式因為路徑有空白,所以用 "" 的話,必須寫成:

START "" "應用程式"
START "" /D "路徑" "應用程式"

用一個空的 "" 文字給 START 當視窗標題文字參數。

所以要不要下 "" 參數,取決於後面是否有用到 "" 符號。


說明

各指令的更完整功能,請用 HELP 指令 查閱。


作業系統自帶功能


*.exe

小算盤
calc.exe

命令提示字元
cmd.exe

檔案總管
explorer.exe

本機
explorer.exe /n,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}

我的文件
explorer.exe /n,::{450D8FBA-AD25-11D0-98A8-0800361B1103}

網路芳鄰
explorer.exe /n,::{208D2C60-3AEA-1069-A2D7-08002B30309D}

資源回收筒
explorer.exe /n,::{645FF040-5081-101B-9F08-00AA002F954E}

小畫家
mspaint.exe

ODBC 資料來源管理器
odbcad32.exe

記事本
notepad.exe

工作管理員
taskmgr.exe


*.msc

電腦管理
compmgmt.msc

事件檢視器
eventvwr.msc

效能監視器
perfmon.msc

服務
services.msc


rundll32.exe

控制台
rundll32.exe shell32.dll,Control_RunDLL

輕鬆存取中心
rundll32.exe shell32.dll,Control_RunDLL access.cpl

新增移除程式
rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl

開啟或關閉 Windows 功能
rundll32.exe shell32.dll,Control_RunDLL appwiz.cpl,,2

藍芽與其他裝置
rundll32.exe shell32.dll,Control_RunDLL bthprops.cpl

顯示器
rundll32.exe shell32.dll,Control_RunDLL desk.cpl

顯示器
rundll32.exe shell32.dll,Control_RunDLL desk.cpl

桌面圖示設定
rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,0

螢幕保護程式
rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,1

背景
rundll32.exe shell32.dll,Control_RunDLL desk.cpl,,2

防火牆
rundll32.exe shell32.dll,Control_RunDLL Firewall.cpl

裝置管理員
rundll32.exe shell32.dll,Control_RunDLL hdwwiz.cpl

網際網路
rundll32.exe shell32.dll,Control_RunDLL inetcpl.cpl

地區
rundll32.exe shell32.dll,Control_RunDLL intl.cpl

遊戲控制器
rundll32.exe shell32.dll,Control_RunDLL joy.cpl

滑鼠
rundll32.exe shell32.dll,Control_RunDLL main.cpl

聲音
rundll32.exe shell32.dll,Control_RunDLL mmsys.cpl

數據機連線
rundll32.exe shell32.dll,Control_RunDLL modem.cpl

網路連線
rundll32.exe shell32.dll,Control_RunDLL ncpa.cpl

電源選項
rundll32.exe shell32.dll,Control_RunDLL powercfg.cpl

系統內容
rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl

電話連線
rundll32.exe shell32.dll,Control_RunDLL telephon.cpl

日期和時間
rundll32.exe shell32.dll,Control_RunDLL timedate.cpl

安全性與維護
rundll32.exe shell32.dll,Control_RunDLL wscui.cpl

新增印表機裝置
rundll32.exe shell32.dll,SHHelpShortcuts_RunDLL AddPrinter

字型
rundll32.exe shell32.dll,SHHelpShortcuts_RunDLL FontsFolder

以上指令尾端,可接 ,,數字 切換頁籤。


進階設定


電源

切換平衡的電源模式為更好的電池
POWERCFG /OVERLAYSETACTIVE OVERLAY_SCHEME_MIN

切換平衡的電源模式為效能更好
POWERCFG /OVERLAYSETACTIVE OVERLAY_SCHEME_NONE

切換平衡的電源模式為最佳效能
POWERCFG /OVERLAYSETACTIVE OVERLAY_SCHEME_MAX

切換電源計畫為省電、平衡、高效能
POWERCFG /S 電源配置GUID(可用 /L 參數查詢)


服務

啟動服務
sc start 服務名稱

停止服務
sc stop 服務名稱

停用服務
sc config 服務名稱 START=DISABLED

刪除無效的服務
sc delete 服務名稱


釘選到工作列或開始畫面

為批次檔建立捷徑,然後在圖示按「滑鼠右鍵」→「內容」,修改「目標」,在前面加上 CMD /C 即可。


恢復命令提示字元視窗的預設值

登錄編輯程式,把 HKEY_CURRENT_USER\Console 刪掉。

刪掉前建議匯出成 .reg 檔,以便反悔時還原。


可能遇到的錯誤


換行

批次檔建議使用 DOS 的 CR+LF 換行,否則執行下一行指令時,可能因為換行失敗,導致錯誤。


字元編碼

如果你的批次檔寫好,以後就不會再修改,那麼用 Windows 預設的在地字元編碼,比如 Big5,顯示中文時比較不會出問題。

但如果這個批次檔是經常會修改的,那建議使用 UTF-8,而不是經常被判讀為 ASCII 的 Big5。

因為,批次檔是一種純文字文件,而純文字文件本身不帶額外訊息(metadata),裡面單純就是只有文字,所以對於檔案本身是用什麼字元編碼,是根據內容有哪些特徵來判讀的。不同系統和應用程式,對於怎樣判讀說檔案內容是哪一種字元編碼,並不一致,你儲存為 Big5 的字元編碼,如果裡面實際上沒有中文,或者只有一個 Big5 編碼的字元,那麼系統或應用程式執行時,有可能視為 ASCII 字元編碼,中文變英文字母。比如以 Big5 字元編碼儲存內含這個指令的批次檔:

git commit -m …

哪天用文字編輯器修改這個批次檔時,文字編輯器可能判讀為 ASCII,然後以 ASCII 儲存後,變成:

git commit -m K

使用 UTF-8 編碼,批次檔裡的非 ASCII 編碼字元,就不會有這種判讀錯誤的問題,能正確判讀為 UTF-8 字元編碼的文件。甚至還可以儲存為帶 BOM 的純文字文件,這樣就等於本身有帶字元編碼訊息的檔案了。

缺點是批次檔裡面有非英文的文字或符號,必須執行這個指令,否則預設使用在地字元編碼的 Windows 會以亂碼顯示:

CHCP 65001


誤用內定符號

有時候用到特殊符號的話,會造成語法執行錯誤,這時看看自己的指令中,是否有用到 + 之類的符號,用 "" 把符號包起來試試,比如寫成 "+"。


附錄


.bat 或 .cmd

.bat 是 DOS 時期逐行執行指令用的檔案,.cmd 是不支援 DOS 的 Windows NT 用 cmd.exe 解譯指令的腳本檔案。

所以批次檔來講,採用 .bat 副檔名才是對的!.cmd 比較像 PowerShell 的 .ps1 那樣的存在。