【轉】Windows批處理學習(二)——批處理(2)

轉自:http://akudy.blog.51cto.com/2277883/1257596


前記

   本篇緊接上一篇繼續探索批處理腳本,上一篇主要介紹了批處理所支持的數據類型以及批處理中常見的符號所表示的意義,這一篇則介紹批處理的常見命令語句的使用方式。閒話少說,直入正題。

DOS批處理的使用

   任何程序設計語言除了提供數據類型的支持、特殊符號的操作處理支持,當然還需要提供分支、循環、跳轉語句的支持才能算的上是完善的語言。批處理的數據類型和特殊符號在上一篇已經介紹過,下面看看批處理中支持的分支語句、循環語句、跳轉語句和其他控制語句。

1.常見內置環境變量

   批處理內置環境變量包括Windows的系統環境變量等,以下只是介紹接個在批處理中常用的批處理環境變量,至於批處理中引用Windows環境變量的用法與引用自身內置變量一樣,關於Windows環境變量可以自行查看資料。

1.1.cd——當前工作目錄

    “cd”是MS-DOS目錄切換的命令,當然它也是MS-DOS提供的內部環境變量,用於引用當前批處理腳本的工作目錄完全路徑名;其實與無參數的“cd”命令的返回結果一樣,當作爲環境變量引用的時候比較方便,可以直接使用“%cd%”表示當前工作目錄。

1.2.date——當前系統日期

   “date”是MS-DOS提供的日期管理命令,同時也是MS-DOS提供的內部環境變量,用於表示當前系統日期,在Windows中通常與右下角日期格式一致。在批處理中可以直接使用“%date%”獲取當前系統日期。

1.3.time——當前系統時間

   “time”是MS-DOS提供的時間管理命令,與“date”命令一樣也是MS-DOS的內部環境變量,用於表示當前系統時間,在Windows中通常與右下角時間格式一致。在批處理中可以直接使用“%time%”獲取當前系統時間。

1.4.random——0~32767之間的隨機數

   “random”是MS-DOS提供的隨機數內部環境變量,該變量返回的是一個0~32767之間的隨機十進制數值。所以當我們需要使用隨機數的時候可以直接使用“%random%”來獲取。

1.5.errorlevel——錯誤級別變量

   “errorlevel”可譯爲“錯誤級別”,是MS-DOS(批處理)內置的用於監聽某些語句執行成功與否的變量。可以將它看作批處理中某一句代碼的返回值,它的結果是一個數值類型的代碼,每一個代碼都表示一種錯誤級別;它與每一條語句進行綁定,也就是說每一條語句都會返回一個錯誤級別代碼並賦值給“errorlevel”變量,當然也有例外的情況,除過“pause”,“cls”,“set”,“echo”,“rem”,“path”,“title”等命令語句外大部分的文件和目錄處理命令行都會返回錯誤級別代碼。至於哪些語句可以返回、哪些語句不返回可以自己測試看看。

   當某一條語句執行成功時將返回“0”,即“errorlevel”等於“0”時表示語句執行成功;如果執行失敗則返回對應的代碼,也就是說如果“errorlevel”爲非“0”的結果都可以視爲上一句代碼執行失敗。也就是說如果返回了錯誤級別代碼就會直接賦值給“errorlevel”變量,之前的值就被覆蓋了,如果沒有覆蓋就說明該條語句沒有返回錯誤級別代碼。

   從上面的介紹可以得知,單單憑藉“errorlevel”變量來獲取某條語句執行結果是不準確的,因爲部分語句是沒有錯誤級別代碼返回的,所以我們可以知道當“errorlevel”變量的值不爲“0”時就代表某處語句發送了錯誤。“errorlevel”變量可以與“if”條件語句一起使用來進行判斷。

1.6.cmdextversion——命令行版本變量

   “cmdextversion”可譯爲“CMD擴展版本號”,是MS-DOS提供的命令行擴展版本號常量,它一般與MS-DOS發行版本有關,第一個版本的時候改變量的值爲“1”,每次對命令擴展名有相當大的增強時,版本號會增加一個。需要注意的是隻有當命令擴展名被啓用的時候才存在變量“cmdextversion”。

   常常使用“cmdextversion”來檢測命令行環境,例如在第二個版本中新增了一個擴展,則在第一個版本中是無法使用的,需要在執行前檢查版本是否爲“2”,如果是則可以成功執行,否則無法執行。實質該變量幾乎用不到。

1.7.cmdcmdline——命令行執行程序

   “cmdcmdline”可譯爲“CMD命令行”,是MS-DOS提供的命令處理器命令行引用的常量,它一般返回的是MS-DOS執行解釋器的完全路徑名。

1.8.path——執行路徑

   “path”可以理解爲“執行路徑”,當指定一個程序名稱後會首先在“path”指定的執行路徑目錄中進行程序搜索,如果搜索到則執行。“path”也可以是一個命令,同時也是一個內置變量,可以通過“%path%”來引用當前批處理程序的執行路徑信息,默認爲Windows系統環境變量中的“path”變量值。

2.批處理控制語句

2.1.pause——批處理暫停

   “pause”命令用於暫停當前批處理程序的執行,並不是終止,只是暫時的停止執行並可以及時恢復執行過程。我們進程會見到一個批處理執行完成後必須按一下鍵盤,才能退出批處理程序,這就是使用了“pause”的效果。當執行到“pause”默認的會在批處理控制檯顯示“請按任意鍵繼續...”字樣,當按下任意鍵時則恢復,繼續執行批處理程序。大多數的情況下都會使用到該命令,用法如下:

pause [...]

沒有任何參數的“pause”命令的實質就是輸出“請按任意鍵繼續...”並監聽按鍵事件觸發,當觸發按鍵後則終止暫停。

   默認情況下,批處理文件一次執行完畢後就自動退出,就是我們看到的大多數情況下“一閃而過”的情況,如果我們想在批處理控制檯輸出什麼信息則都無法查閱;現在就可以使用“pause”命令在批處理執行完成退出之前進行批處理程序的暫停操作,則就可以保留MS-DOS解釋器的窗口,從而查看MS-DOS的控制檯信息。我們來分析一下的代碼:

1
2
3
pause
pause > a
pause > nul

保存爲“.bat”文件後執行可以看出,第一條語句執行的結果爲“請按任意鍵繼續...”並等待按下任意鍵;第二條語句執行的結果爲什麼也沒有輸出,而是在當前工作目錄中新建了一個名爲“a”的文件,內容是“請按任意鍵繼續...”,同時等待按下任意鍵;第三條語句執行的結果是沒有輸出內容和新建“nul”文件並等待按下任意鍵。來分析一下代碼,“>”用於將命令的執行響應信息輸出到指定的文件,所以“pause > a”會將“請按任意鍵繼續...”輸出到名爲“a”的文件中,那麼爲什麼“pause > nul”沒有輸出到文件呢?

   “nul”是一個特殊的字符串,在批處理中它表示“空字符”,它是一個概念上的空字符,表示沒有值,不是我們所說的空白符。上面的例子中的“pause > nul”意思就是說輸出空內容,所以即不輸出內容,也不輸出到文件。也就是說,我們可以使用“pause > nul”來取消“pause”命令的輸出內容。

2.2.echo——回顯設置

   關於批處理的回顯問題,在上一節已經講到過,“回顯”就是打印要執行的命令語句,也就是每執行一條命令語句,都會先打印出來,然後在執行,當然這樣查看程序執行過程比較混亂,所以大多數情況下需要關閉回顯功能。上一節提到了“@”符號作爲命令的前綴用於關閉該命令的回顯功能,如果要關閉所有的命令回顯功能,則需要在每一個命令前加上“@”符號,比較繁瑣,下面就來介紹一種簡單的處理方式——“echo”命令語句。

   “echo”命令語句在批處理中,有兩個作用:其一就是控制當前批處理程序的回顯打開或關閉的狀態設置,其二就是在MS-DOS解釋器控制檯輸出信息。第二種作用前面已經用到很多次了,可以自行嘗試一下。下面來看看使用方式:

echo [ON | OFF]

echo 信息

echo符號 [ON | OFF | 信息]

   首先來看第一種方式,演變爲“echo”、“echo on”或“echo off”三種方式,其中無參數的“echo”命令用於查看當前“echo”狀態(即回顯狀態),默認情況下是開啓的;“echo on”命令可以開啓回顯;“echo off”命令用於關閉回顯,“echo off”的關閉可以適用與當前批處理程序,如果沒有顯示打開,即使用“echo on”命令,則當前批處理的回顯狀態一直處於關閉狀體,所以我們可以使用“echo off”來代替繁瑣的“@”命令回顯屏蔽符號。例如我們最常用的兩種方式:

1
2
echo off
cls

1
@echo off

第一種方式我們調用了“echo off”命令關閉了當前批處理的回顯狀態,而“echo off”命令在執行前,回顯是開啓的,所以使用“cls”來清空屏幕內容;第二種發送直接使用“@”符號屏蔽“echo”命令的回顯功能;從而達到關閉所有回顯狀態。關於回顯狀體的設置,我們通常都在批處理的開頭設定,因爲這樣比較合理,所以建議使用“@echo off”命令。

   再來看第二種方式“echo 信息”,可想而知用於在控制檯輸出“信息”,其實這個信息就是你要輸出的字符串,這種方式比較容易理解。要輸出的內容緊接“echo”命令之後,注意必須使用空白符進行分割。我們來看下面的例子

1
2
3
@echo off
echo Hello World!
pause > nul

保存爲批處理文件並執行,可以看成在控制檯只輸出了“Hello World!”信息,沒有其他信息,可以看出“@echo off”關閉回顯功能已經起效。

   最後看第三種方式“echo符號[信息]”,爲什麼會多出一個“符號”呢?首先看看我們如何輸出“off”和“on”字符,可見使用第二種方式執行後實質就是第一種方式設置回顯狀態的命令,根本達不到輸出“off”或“on”的目的。所以批處理提供了一種特殊的方式來輸出像“off”或“on”這樣的特殊命令字符,使用“echo+符號+字符”的方式來輸出。例如:

1
2
3
4
5
@echo off
echo.off
echo.
echo.msg
pause > nul

保存爲批處理文件並執行,輸出的內容爲:

off

(空行)

msg

上面的例子中,我們使用了特殊符號“.”,從例子可以看出無信息的“echo.”表示的是輸出一個空白行,有信息的“echo.信息”命令等同於“echo 信息”輸出信息用法。

   事實上,批處理輸出空白行的方式有多種,都是使用“echo特殊符號”的方式輸出。當特殊符號後緊接特殊命令字符的時候,特殊符號用於將特殊命令字符轉義爲普通字符;當特殊符號後緊接普通字符是直接輸出,類是於“echo 普通字符”方式。批處理中對“echo”命令提供的“特殊符號”有數十種,也就是說輸出空行的命令有多種方式。其中提供的特殊符號包括“=”、“,”、“;”、“+”、“/”、“[”、“]”、“:”、“.”、“\”,使用“echo”集合任何一種特殊符號都可以輸出空白行。

   可以將上面的特殊符號分爲三組,第一組有“=”、“,”、“;”,它們默認都是批處理中的特殊分隔符號,其實可以將分隔符看作命令參數或選項的一部分,通常批處理命令在執行帶有分隔符的參數是會直接跳過第一個符號,也就是分隔符,而“echo”命令跳過分隔符後其後的字符爲“NUL”,所以輸出了空行,而當分割符爲“空白符”時會跳過並解析其後的字符是否是命令參數;第二組有“+”、“/”、“[”、“]”,它們不是特殊的分隔符,所以會將其作爲一個整體進行解析,但是“echo/”等又不是MS-DOS命令,所以會作爲外部命令來搜索和執行,它們可以作爲外部命令進行執行;第三組有“:”、“.”、“\”,既不是特殊分隔符,也不是外部命令,在執行的過程中,會嘗試自動修復命令進行命令的修復轉換,所以它們的效率是極低的。(信息來自“批處理技術內幕”介紹)

   通過後面的簡單介紹其實爲了說明一定,從執行效率上來將,當使用“echo”命令輸出空行時可以優選考慮使用“echo=”或“echo,”或“echo;”命令,上面所列車的三組符號中,每組的效率依次遞減。

2.3.rem/::——代碼註釋

   任何一種編程語言,都必須存在註釋標識才能讓別人讀的懂。批處理腳本同樣也提供了代碼註釋功能,主要通過“rem”命令來實現文檔註釋說明。“rem”命令用於在批處理或“CONFIG.SYS”文件中標註註釋信息,用法與“echo”輸出命令一樣,在命令後標準一段字符串作爲註釋信息。使用方式如下:

rem 註釋說明信息

“註釋說明信息”可以是任意文字,也可以是一條命令語句,被註釋的語句和文字不參與解釋執行。例如:

1
2
3
4
@echo off
rem echo 空行
echo,
pause > nul

保存並執行的結果爲輸出一個空行,而“rem”後的“echo”語句並沒有執行。

   在批處理中還存在符號“::”與“rem”命令的作用一致,可用於語句的註釋說明。用法與“rem”也一樣,如下:

::註釋說明信息

“::”是一個特殊符號,併發批處理腳本規範的註釋命令,在批處理中使用“::”標註的語句或字符串,作爲無效信息,在執行過程中將直接忽略;而“rem”標識則會解釋爲“rem”命令的作用。也就是說在作用上它們是相同的,但是在原理上就不同了。其實“::”用於彌補“rem”命令的某些不足存在的,在某些特殊的情況下,使用“rem”命令註釋帶有“>”、“<”、“>>”、“|”等特殊符號的時候不能達到預想的效果,但是可以使用“::”來進行註釋。

2.4.set——變量管理

   變量,一般的編程語言中都存在這個名稱,它表示一個可變的量,可以在程序中寄存一個數據項,並在其他的地方引用。從批處理支持的數據類型來看,批處理腳本中變量的類型應該有字符串和數值兩種。講到變量,就得提提變量的名稱了,批處理腳本中對變量的名稱沒有做任何規定,可以是任意符號或字符串,當然也可以是數值,所以說批處理腳本是比較弱智的。

   批處理中的變量主要使用“set”命令來維護和管理,而在批處理中的變量也稱爲環境變量。批處理規定的“set”命令用法比較多,主要有以下四種用法。

1.“set”命令查看變量

   “set”命令可以用於查看變量信息,它返回的是所有符合的變量列表,格式爲“變量名=值”。用法比較簡單,如下:

set [變量名前綴]

這裏“變量名前綴”的意思是指“set”命令會在所有變量中進行查找,如果某個變量名的前綴(從第一個字符開始到第N個字符)與所給定的變量字符串相匹配則將改變了視爲要查找的變量,是一種前綴查找方式。當沒有指定任何變量前綴時則列出所有的變量列表。

2.“set”命令管理字符串變量

   “set”命令可以實現字符串變量的定義和刪除等操作。用法比較簡單,如下:

set 變量名=[值]

這裏使用了一個“=”緊跟在變量名稱後,表示定義一個變量並進行賦值,這裏如果把“=”省略了則變爲查看變量命令了。因此當需要定義變量的時候不可缺少“=”,“值”是可選項,當存在時則表示給當前變量賦值;如果不存在則表示刪除當前變量,也就似乎給變量賦空值。可以參考下面的例子:

1
2
3
4
5
6
@echo off
set var=abc
echo var=%var%
set var=
echo var=%var%
pause > nul

保存爲批處理文件並執行,輸出的內容爲:

var=abc

var=

當給指定變量賦空值時表示移除該變量。

3.“set”命令管理數值變量和運算

   “set”命令不僅可以管理字符串變量,同樣可以管理數值類型的變量。批處理中使用“set /a”命令來實現數值的運算操作,“/a”是“set”的一個選項,表示其後的字符將被作爲數值和算術操作符進行處理,如果不是數值將提示錯誤。用法如下:

set /a 數值表達式

這裏的“數值表達式”不是一個固定的值,而是一種由數字和符號組成的任何一種算術表達式。表達式可以包含前面介紹的任意一種或多種“數值類型符號”,具體符號可以參考具體說明。例如,“set /a result=123+345”,則表示將“123+345”的計算結果賦值給“result”變量;而“set /a 123+345”在表示計算“123+345”的結果;同時還支持簡單的位運算等,支持“()”優選運算,支持“,”多個表達式同時運算等特點。例如:

1
2
3
4
5
6
7
@echo off
set /a a=1,b=2
set /a result=%a%+%b%
set result1=%a%+%b%
echo 算術運算:%a%+%b%=%result%
echo 字符串:%a%+%b%=%result1%
pause > nul

保存爲批處理文件並執行,輸出的內容爲:

算術運算:1+2=3

字符串:1+2=1+2

從例子可以看出,如果要進行數值運算,必須使用“set”命令的“/a”選項來標明。

4.“set”命令實現控制檯輸入

   下面來介紹“set”命令的另一個擴展功能,從控制檯或其他設備或文件將信息讀取一行字符串並賦值給指定的變量。使用“/p”選項來啓用這個功能,用到的較多的地方就是讀取從控制檯輸入的字符串。當解釋器執行到“set /p”命令時會等待用戶的輸入完成,一般使用回車鍵表示輸入完成;在輸入過程中可以使用“CTRL+C”快捷鍵強制退出輸入狀態。用法如下:

set /p 變量名=[值]

只是在定義字符串變量的操作之前加上了“/p”選項,其中“/p”選項表示將啓用控制檯輸入功能,並將輸入的內容賦值給“/p”後指定的變量名,注意“=”不能缺少。當然也可以賦給變量初始值,但是當輸入完成後變量將被重新賦值。例如:

1
2
3
4
@echo off
set /p info=請輸入內容:
echo 你輸入的內容爲:%info%
pause > nul

保存爲批處理文件後可以自行測試。

2.5.cls——清屏

   “cls”命令,在MS-DOS那一節已經講過了,主要用於清除當前屏幕(包括當前語句)中的所有顯示信息,當感覺屏幕內容較多或較混亂時可以使用,用法比較簡單,它沒有多餘的選項。下面看一個例子,使用“cls”命令清除回顯內容實現“@echo off”命令的效果:

1
2
3
4
rem cls清除屏幕內容
echo cls的使用
cls
pause > nul
2.6.color——批處理顯示顏色設置

   “color”語句用於設置當前批處理MS-DOS控制檯的前景(顯示字體)和背景顏色,可以使用該命令來設置當前會話中別緻的命令行窗口。用法如下:

color [前景顏色值[背景顏色值]]

“color”主要用於設置MS-DOS控制檯顏色值,MS-DOS系統使用的十六進制的數值來表示16種顏色,數值與顏色描述表如下:

顏色值 顏色描述 顏色值 顏色描述 顏色值 顏色描述
0 黑色 6
黃色
C 淡紅色
1 藍色 7 白色 D 淡紫色
2 綠色 8 灰色 E 淡黃色
3
湖藍色
9
淡藍色
F 亮白色
4 紅色 A
淡綠色


5 紫色 B

淡淺綠色



   針對“color”語句來說,無參數的“color”語句可以將當前MS-DOS控制點前景和背景顏色還原爲默認值,默認前景爲白色字體,背景爲黑色;對於有參數的“color”語句,第一個顏色值表示前景顏色,第二個顏色值表示背景顏色;如果只有一個值則表示設置前景顏色,也就是顯示文本顏色。

   有一點需要注意的是,如果前景和背景顏色值相同時會導致顏色衝突,所以MS-DOS會將“errorlevel”錯誤級別設置爲1,表示設置顏色異常;也即是說MS-DOS不允許前景和背景顏色設置爲同一個顏色值。

2.7.title——批處理程序標題設置

   “title”命令語句用於設置當前執行批處理命令提示窗口的窗口標題,和“color”命令差不多都用於設置批處理程序的。當需要自定義命令行窗口標題是可以使用該命令實現。用法比較簡單:

title 標題內容

只需要在命令後緊跟標題信息即可。理論上將“title”爲設置批處理標題,實際上它用於改變批處理標題,批處理程序默認的標題爲當前“cmd.exe”程序的執行路徑,當執行到“title XXX”命令時,會將批處理程序運行窗口的標題更改爲“XXX”字樣信息,如果再執行一次“title aaa”則會修改爲“aaa”標題。

2.8.more——分頁顯示

   “more”命令語句用於分頁顯示命令語句響應的內容,也就是控制檯輸出的內容。當某個命令語句的輸出信息太多時就比較凌亂,可以使用“more”命令來實現分頁輸出的效果。之前在介紹“type”命令的時候使用過了“more”語句,當時使用的命令語句是“type a.txt |more”,這只是“more”命令的常見的用法,實質上“more”主要用於查看文件內容。

1.分頁查看控制檯顯示內容

   當一個命令語句的響應信息較多時,可以使用“more”命令來實現分頁查看的效果,常使用管道重定向符號“|”將命令行的輸出信息作爲“more”命令的輸入信息進行處理。用法如下:

命令行語句 | more [more命令選項

從用法規則上看,“| more”命令作爲某個命令語句的子語句,其中管道重定向符號“|”用於將命令行語句的輸出信息作爲“more”命令的輸入內容進行處理,從而達到對命令行輸出信息的分頁查看效果。

2.分頁查看文本文件內容

   “more”命令不僅可以接收MS-DOS控制檯的輸出信息,同樣可以接收MS-DOS從文件讀取的信息,這種用法非常類似“type .. | more”命令查看文件內容的用法。用法如下:

more [more命令選項] [<] [files]

“more”命令可以替換“type”來實現文件內容的友好顯示。其中輸入重定向符號“<”是可選項,當然爲了標準可以明確標識;當要查看的文件未指定時,則接下來的輸入信息將作爲查看的內容,如果要同時查看多個文件,則文件名需要使用空白符分割,實質是將文件內容拼接後顯示的。

   “more”命提供豐富的處理選項,可以通過“more/?”或者“help more”命令來查看,其中“/C”選項可以在顯示下一頁內容前清除屏幕信息;“/S”選項可以將多個空白行縮爲一行進行顯示;“/E”選項可以啓用“more”名的擴展功能,從而實現對子命令的支持,例如可以通過“S n”子命令來跳過下一頁的n行信息等,具體說明可以查看使用說明。

2.9.if——條件判斷(分支)語句

   “if”語句是批處理中的條件分支語句,表示的意思就是“如果...則...否則...”,大多用在批處理程序中的條件處理部分。“if”語句在批處理中使用的是比較廣泛的,例如要查看某個文件,則首先要確定該文件存在纔可以查看,否則MS-DOS會拋出錯誤信息,這個時候就可以使用“if”語句進行判斷。“if”命令語句是通過條件成立與否來決定語句的執行,這裏的條件成立和條件不成立可以理解爲“true”和“false”,但是批處理中不存在這兩個常量。“if”語句所表達的意思是隻有當條件成立時纔會執行指定的命令語句,主要有以下幾種用法。

1.判斷信息是否相等(“==”)

   “if”命令語句就是用於條件的判斷,然而由於批處理腳本本身比較弱化,所以初始的MS-DOS只能支持信息相等的比較,也就是隻支持“==”操作符。用於比較字符串與字符串、變量與變量、變量與字符串之間是否相等,如果相等則表示條件成立。用法如下:

if [not] 信息比較表達式 (

   命令行1

) else (

   命令行2

)

這裏的“信息比較表達式”的格式爲“字符串1==字符串2”或“變量1==變量2”或“變量==字符串”的形式,也即是說只能使用“==”進行字符串或變量之間的比較,上面的“not”表示相反操作,不做多的解釋,來看下面的例子:

1
2
3
4
5
6
7
@echo off
if abc==ABC (
   echo abc euqal ABC
else (
   echo abc not euqal ABC
)
pause>nul

保存爲批處理文件,執行既可以看到效果,可以自行修改,添加“not”試試。

2.判斷錯誤級別信息

   錯誤級別“errorlevel”是MS-DOS的內置環境變量,在上面已經介紹過,主要用於保存上一條命令語句是否執行成功,成功則返回0,失敗或錯誤則返回相對應的錯誤級別碼。然而“errorlevel”是內置環境變量,所以可以使用下面的方式判斷:

1
2
3
4
5
6
7
@echo off
if %errorlevel%==0 (
  echo success!
else (
  echo failed!
)
pause>nul

然而“if”語句提供了一種特殊的錯誤級別判斷方式,如下:

if [not] errorlevel number (

   命令行1

) else (

   命令行2

)

這種方式並不是使用變量的方式進行引用,而是作爲關鍵字使用,“number”表示一個錯誤級別碼,“not”表示相反操作,不做多的解釋。使用這種方式比較簡潔。

3.判斷文件是否存在

   在上面已經提到關於文件是否存在的判斷,“if”語句提供了一種特殊的文件判斷方案,用法如下:

if [not] exist filepath (

   命令行1

) else (

   命令行2

)

其中“exist”是關鍵字表示“存在”,“filepath”表示要判斷的文件路徑,如果檢查到指定的文件存在則執行對應的命令塊,“not”表示相反操作,不做多的解釋。多說無益,直接看例子:

1
2
3
4
5
6
7
8
@echo off
if exist C:\a.txt (
  echo file is find!
del C:\a.txt
else (
  echo file is not found!
)
pause>nul

上面的例子表示如果檢查到C盤存在“a.txt”文件則刪除該文件,保存爲批處理文件試試即可。

4.判斷MS-DOS擴展版本號(擴展用法)

   MS-DOS擴展版本號“cmdextversion”是MS-DOS的內置環境變量,在上面已經介紹過,當在使用某個新擴展特徵時可以首先判斷版本號是否對應,不過該用法需要在啓用命令擴展之後才能使用,而命令擴展默認是啓用的,進行擴展版本號判斷是“if”語句的擴展用法。用法如下:

if cmdextversion number (

   命令行1

) else (

   命令行2

)

意思是說噹噹前批處理擴展版本號與給定的“number”值對應時執行“語句1”否則執行“語句2”,大多數情況下不會使用這個命令語句。

5.判斷變量是否存在(擴展用法)

   變量是否存在的檢查是“if”語句的擴展用法,用法比較廣,可以判斷變量是否被聲明,然後在斟酌使用,不過該用法需要在啓用命令擴展之後才能使用,而命令擴展默認是啓用的,用法比較類似文件是否存在的判斷用法,如下:

if defined 變量名 (

   命令行1

) else (

   命令行2

)

當變量被聲明定義後“defined 變量名”纔會成立,否則不會成立,具體實例可以自行編寫。

6.信息比較運算(擴展用法)

   上面介紹過“if”默認情況下只支持相等比較運算,然後後續考慮則對“if”語句進行了命令擴展,使其可以支持多種比較運算操作,不過該用法需要在啓用命令擴展之後才能使用,而命令擴展默認是啓用的。用法與“if”相等比較運算的用法一致,如下:

if [/i] 操作數1 比較運算符 操作數2 (

   命令行1

) else (

   命令行2

)

其中操作數可以是字符串也可以是數值,同時還可以是變量;“/I”選項用於開啓比較過程中字符串大小寫忽略功能;在命令擴展下支持的比較運算符有:“equ(等於)”、“neq(不等於)”、“lss(小於)”、“leq(小於等於)”、“gtr(大於)”、“geq(大於等於)”六種,其中“lss”、“leq”、“gtr”和“geq”四種比較操作符主要用於對數值進行比較,當參與比較的字符串是字符串時,將被轉換爲對於的ASCII碼進行比較;而“equ”和“neq”既可以比較數值也可以比較字符串。來看下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@echo off
set var1=123
set var2=abc
set var3=12
if /i %var2% equ ABC (
  if %var1% geq %var3% (
    echo %var1%^>=%var3%
  else (
    echo %var1%^<%var3%
  )
else (
  echo %var2%不等於ABC
)
pause>nul

上面的例子可以說明“/I”的用法,以及其他命令擴展下的操作符用法,保存爲批處理文件即可執行查看效果。

   綜上所述,特別提示以上的“if”語句中的“else”子句是可省略的,“else”只是起到多分支的作用,表示當條件不成立時執行的處理過程,不必要時可以去掉。關於“()”表示範圍,用於表示多條語句執行的語句塊(批處理中的每一條語句都是以換行符作爲結束符號的),也就是說當條件成立是會執行“if”後“()”內的所有語句,當只有一條語句需要執行時可以省略“()”,特別需要注意的是省略“()”時,命令和“if”語句必須寫在一行,當有“else”子句時必須使用“()”。【小提示:注意“()”與關鍵字之間的空格】

2.10.setlocal/endlocal——啓動/結束延遲環境變量擴展功能

   前面已經介紹過變量的引用原理,就是查找變量名對應的值來替換“%變量名%”字符串,從而達到變量引用的效果,這個過程也稱之爲變量擴展過程,這種過程可用於處理基礎的普通的變量,然而我們來看看下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
@echo off
set var=before
if "%var%" == "before" (
  set var=after
  if "%var%" == "after" (
    echo 重置var的值成功[var=%var%]
  else (
    echo 重置var的值失敗[var=%var%]
  )
)
echo var=%var%
pause>nul

按照正常的執行流程可以推斷出結果爲“重置var的值成功[var=after]”,然而真實執行的結果並不是我們想象的,保存爲批處理文件並執行輸出的結果爲“重置var的值失敗[var=before]”。我們來看看爲什麼爲出現這種情況?首先聲明瞭變量var的值爲before,緊接着爲一個“if”語句,又在“if”語句中對變量var進行重新賦值,然後在進行判斷,然而該程序在解釋執行的過程中,將“if”語句以及其內的“set”命令和“if”語句作爲一整條語句進行解釋的,當遇到“%var%”時會自動查找“var”的值替換當前語句,也就是整個外層“if”語句中的所有“%var%”字符串,因此內部的“if”判斷條件中的“%var%”被替換成了“before”,所以永遠都不會與“after”相等。這就是變量擴展的過程,那麼外層“if”語句中的“set var=after”是否執行了呢?答案是肯定的,通過在程序末尾追加“echo var=%var%”可以看出。

   通過上面的例子,可以得出一個結論就是批處理中的默認變量替換過程值針對一整條語句的,也就是說如果一整條語句中某個地方有變量的引用,則將會影響到該條語句中的所有變量引用,同一條語句中的所有變量引用會在同一時刻被替換爲該變量對應的值。通俗的說,就是默認情況下,一條語句中的變量的值是固定的。

   針對這個現象,批處理提出了延遲環境變量(簡稱延遲變量)的概念,主要用於對變量進行擴展,彌補普通變量的應用過程中的不足,通過延遲環境變量可以實現在一整條語句中改變變量的值。也就是說可以通過延遲環境變量概念來實現子句內部的變量聲明、定義和賦值等操作。批處理中給出了“setlocal”和“endlocal”命令來實現延遲變量擴展功能的開啓和關閉操作,來看看兩個命令的用法:

setlocal enableExtensions | disableExtensions

setlocal enableDelayedExpansion | disableDelayedExpansion

endlocal

“setlocal”命令有兩種用法,第一種用法用於啓動(enableExtensions)或者停用(disableExtensions)命令處理器擴展名功能,這個用法主要用於管理MS-DOS解釋器的命令擴展功能,默認是開啓的,一般很少用到;第二種用法就是現在介紹的用於啓動(enableDelayedExpansion)或者停用(disableDelayedExpansion)延遲環境變量擴展功能,默認是停用的。“endlocal”命令用法比較簡單,就一個單一的命令行,該命令行主要用於停用延遲環境變量擴展功能,命令執行後將會還原當前批處理的擴展功能爲默認值,所做的環境變量的改動不在侷限於當前批處理文件;實質上“endlocal”比較特殊,是可以省略的,也不是一定要與“setlocal”成對出現,當一個或多個“setlocal”沒有強制使用“endlocal”時會在批處理文件的末尾自動執行“endlocal”命令來還原初始默認設置。

   當開啓延遲環境變量的擴展功能後,對環境變量的修改和引用將會擴展到整個批處理程序中。下面來看看如何使用延遲環境變量的擴展功能?現在使用延遲環境變量擴展功能解決上面遇到的問題,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
@echo off
setlocal enableDelayedExpansion
set var=before
if "!var!" == "before" (
  set var=after
  if "!var!" == "after" (
    echo 重置var的值成功[var=!var!]
  else (
    echo 重置var的值失敗[var=!var!]
  )
)
pause>nul

在這段代碼中,首先使用“setlocal enableDelayedExpansion”語句啓用了延遲環境變量擴展功能,保存爲批處理文件並執行的結果則爲預想的效果“重置var的值成功[var=after]”,代碼中並沒有強制使用“endlocal”語句停用延遲環境變量擴展功能,但是MS-DOS解釋器會在程序的末尾,也就是“pause>nul”語句之後自動調用“endlocal”命令重置MS-DOS環境默認值。

   但是上面的代碼與之前的代碼還有一處細小的區別,就是這裏使用了“!xxx!”的方式來引用變量。然而爲什麼要使用這種方式呢?“%xxx%”的方式是否可行?答案可想而知“%xxx%”的方式肯定不可行。之前已經介紹過“%xxx%”方式的變量替換原則,當在一條命令的整體語句中時,如果首次遇到“%xxx%”的字符串,則會自動查找並替換該整條語句中的所有“%xxx%”字符串爲指定變量的值;正是這個原因,所以提出了延遲環境變量擴展的概念,延遲環境變量擴展就是爲了解決整條語句中所有變量被替換的問題,然而在提出延遲環境變量擴展概念的同時擴展了“!xxx!”的變量引用方式,主要用於區別默認的“%xxx%”變量引用方式,而且“!xxx!”變量引用方式只能在延遲環境變量擴展功能開啓的環境中才能被解析。

   來總結以下,關於延遲環境變量擴展的用法,延遲環境變量擴展功能主要用於解決像“if”、“for”以及各種複合語句(使用邏輯運算符拼接的語句)等中,用於在語句內部引用修改後的變量,因爲默認情況下語句中的變量是被提前替換的,使用延遲環境變量則可以延遲替換過程到解析到該變量時;使用“setlocal enableDelayedExpansion”語句開啓延遲環境變量擴展功能後,只能使用“!xxx!”的方式引用變量,表示該變量將被作爲延遲環境變量進行處理,如果使用“%xxx%”方式引用將繼續作爲普通變量處理;開啓延遲環境變量擴展功能後可以在必要的時候強制使用“endlocal”或“setlocal disableExtensions”語句停用該功能,默認在程序結尾自動調用“endlocal”語句進行重置。

2.11.for——循環語句

   對於一門程序語言,單單提供分支語句是不夠的,必須還要提供循環語句才能滿足重複執行某一項任務的需要。在批處理腳本程序中同樣提供了循環語句——“for”語句,主要用於實現重複執行某一項命令,“for”語句設計由衷用於對一組文件中的每一個文件執行某項特定的命令操作,同時也可以擴展爲對一個集合中的每一個元素執行某項特定的命令操作。“for”語句主要有一種基本用法和四種擴展用法,下面將一一介紹。

1.循環遍歷元素(基本用法)

   批處理中的循環主要用於遍歷集合中的元素,語法結構如下:

for %%臨時變量名 in (集合列表) do (

   命令行

)

基本結構比較簡單,使用“for...in...do”的方式,字面意思就是“把在集合中的所有元素都執行一遍操作”,使用這種方式將一個集合中的所有元素都執行一次相同的命令。

   在循環遍歷過程中如何取得每一個元素呢?在批處理中的循環語句中提供了一個臨時變量用於保存每一個元素(不區分元素類型),從語法上可以看出“%%臨時變量名”就是這個臨時變量。這裏的臨時變量的聲明與之前將的環境變量的聲明不大一致,環境變量的聲明直接使用“xxx”方式,而在“for”語句中的臨時變量聲明使用“%%xxx”方式。至於爲什麼這樣規定,我也沒有搞清楚,之前介紹過“%”有轉義的作用,所以這裏的第一個“%”可以看作爲轉義字符,正式的變量名爲“%xxx”,或許是爲了區分環境變量(語句外定義)或語句內變量。需要注意的是臨時變量“%%xxx”中的“xxx”可以是任意字符,而且必須是單個字符,當爲英文字母時其名稱是區分大小寫的,爲什麼只能爲一個字符下面會通過例子介紹到。由於“%%xxx”格式的臨時變量保存的是一個元素,所以可以直接在“for”語句內部使用“%%xxx”方式來訪問該臨時變量,這一點也與環境變量的訪問方式不同。

   關於集合列表中的值,可以是任意值,多個值使用英文狀態的逗號(“,”)分割開來,而且集合無論有多少值都必須使用“()”括起來,表示一個集合範圍。上面說過“for”語句的由衷就是爲了遍歷一組文件,所以不管集合列表中是什麼值,都作爲文件名來處理,無論該文件是否存在都會進行遍歷,默認情況下只是作爲文件名(字符串)進行處理,當然還可以進行更高級的擴展處理。也就是說,事實上看到的字符串,實質是作爲文件名進行處理的,所以元素支持通配符“*”和“?”,“*”表示當前工作目錄下的所有文件。多說無益,看下面的例子:

1
2
3
4
@echo off
rem for變量元素例子
for %%i in (1,3,5,7) do echo %%i
pause > nul

上面的例子用於變量所有的元素,其中1,3,5,7將作爲文件名進行輸出。保存爲批處理文件並執行可以看看結果。

1
2
3
4
5
6
@echo off
rem for混合元素例子
for %%i in (1,*) do (
  echo %%i
)
pause > nul

上面的例子用於變量每一個元素,其中“*”表示當前工作目錄下的所有文件,並將文件名打印輸出,保存爲批處理文件執行即可看到效果。

   上面的兩個例子足以說明“for”語句的基本用法,其中如果要重複執行的語句爲多條語句時必須使用“()”將多條語句括起來,與“if”基本相識;如果是單條語句可以直接寫在“do”後面。

2.循環遍歷目錄(擴展用法)

   批處理中的“for”語句默認是用於遍歷文件列表的,如果想變量一個目錄列表又該如何操作?在批處理的“for”語句結構中提供了一個“/D”選項,可以將集合列表中的元素值強制作爲目錄名稱進行處理。語法結構如下:

for /D %%臨時變量名 in (集合列表) do (

   命令行

)

該用法只是在基本用法的基礎上,多了一個“/D”選項用於修飾臨時變量,主要是將臨時變量的值進行目錄檢查,如果是目錄則取用,否則則丟棄。看下面的例子,在C盤下的文件夾中存在文件和子文件夾:

1
2
3
4
5
6
7
@echo off
cd C:\test
echo 文件有:
for %%f in (*) do echo %%f
echo 目錄有:
for /d %%d in (*) do echo %%d
pause > nul

通過上面的代碼執行結果的對比可以看出“/d”選項的作用,用於匹配目錄名稱,忽略文件。

3.循環遍歷指定工作目錄下的文件或目錄(擴展用法)

   在第二個用法的例子中開頭有一句“cd C:\test”將當前工作目錄切換到C盤的test目錄,如果不指定則默認工作目錄就是當前批處理所在的目錄,這樣寫雖然很直觀當時相對比較麻煩。在批處理的“for”語句中提供一種指定工作目錄的方式,使用“/R”進行工作目錄的指定,用法如下:

for [/D] /R 工作目錄 %%臨時變量名 in (集合列表) do (

   命令行

)

該用法是基礎用法的擴展用法,可以直接在“for”語句內指定要查找的工作目錄,使用“/R 工作目錄”的方式指定。指定後將在當前“工作目錄”中進行文件的查找遍歷。當然可以與“/D”一起使用,用於查找變量目錄,當與“/D”一起使用時“/D”修飾必須寫在“/R 工作目錄”的前面。下面我們來改寫第二個用法中的例子,如下:

1
2
3
4
5
6
@echo off
echo 文件有:
for /r C:\test %%f in (*) do echo %%f
echo 目錄有:
for /d /r C:\test %%d in (*) do echo %%d
pause > nul

保存爲批處理文件並執行則可以看到執行結果與第二個用法的基本一致,只不過這個用法輸出的是文件或目錄的完全路徑名稱,這是“/R”選項的另一個特點。如果你細心,還會發現“/R”選項還可以查找變量到目錄下的子目錄或子文件,如果我們在C:\test目錄下的某一個目錄下再添加一個文件或目錄,則同樣會打印輸出。

   來總結一下“/R 工作目錄”的用法,可以查找當前工作目錄下的所有文件或目錄,包括子目錄下的文件或目錄,直到沒有下一層爲止;每一個臨時變量保存的是文件或目錄的完全路徑名稱。也就是說使用這種方式我們可以實現目錄結構樹圖,可以自行嘗試一下。再來看看上面講到的兩種用法,基礎用法和“/D”選項用法只能查找當前工作目錄下的文件或目錄,而並不能進一步深入查找下一層文件或目錄。

4.固定頻率循環(擴展用法)

   上面介紹的“for”語句主要用於文件管理中的循環遍歷操作,這些循環操作執行的次數都是受到工作目錄中文件或目錄的數量的影響,是不固定的;當我們需要執行規定次數的某一個操作時,又該如何實現呢?當我們要迭加一個數值又該如何實現呢?其實在批處理的“for”語句中提供了“/L”選項,專門用於實現數值範圍的遍歷操作,用法如下:

for /L %%臨時變量名 in (start,step,end) do (

   命令行

)

從語法結構上看,添加了一個“/L”選項修飾操作,同時“集合列表”也固定了結構,是一個有start、step、end三個數值組成的列表,從語義上可以知道集合列表中的“start”表示循環的開始數值,“end”表示循環的結束數值,而“step”表示循環的遞增頻率數值;過程是第一次循環臨時變量將被賦值爲“start”指定的數值,之後每一次臨時變量在原有值的基礎上增加“step”指定的數值,然後與“end”指定的值進行比較是否小於等於,如果是則執行下一次循環,否則跳出循環。舉個例子,如果我們要循環3次則列表集合可以寫作“(1,1,3)”,就是說臨時變量從1開始,到3結束,每一次循環後增加1;如果要打印輸出10以內的奇數,則可以寫作“(1,2,10)”。多說無益,來看下面的例子:

1
2
3
4
5
6
@echo off
echo 10以內的奇數:
for /l %%i in (1,2,10) do echo %%i
echo 10以內的偶數:
for /l %%j in (10,-2,1) do echo %%j
pause > nul

保存爲批處理並執行既可以看到結果。“for”語句使用“/L”選項後,要求集合列表必須包含3個數值,其中第一個表示循環起始值,第二個表示循環頻率值,第三個表示循環結束值,這些值必須是數值,而且可以爲正負數值。

5.高級擴展應用

   上面已經介紹了“for”循環的幾種不同應用方式,但是不足以靈活多變,所以批處理還提供了高級擴展應用,包括文件內容循環遍歷、內容查找處理操作、動態執行命令行等功能。高級擴展應用使用“/F”選項進行開啓,用法如下:

for /F [操作選項] %%臨時變量名 in (集合列表) do (

   命令行

)

擴展用法與上面介紹的幾種基本一致,不過這裏在“/F”選項後包括一個“操作選項集合”,下面會介紹到。

   首先來看看“集合列表”,集合列表可以是文件集合、字符串集合(我們知道文件都是擴展名的,或許可以簡單的區分爲文件名或字符串)或命令集合。當集合中的元素爲一個或多個文件時,則在進入循環語句時,當前文件和之前已經遍歷的文件都將處於打開狀態,並接受讀取等操作,處理包括讀取文件行(將文件內容以換行符分割或空白符截斷)並將每一行信息解析爲一個或多個字符串(按操作語句指定進行解析分割),當爲文件名時需要注意的是當文件名中有空格符號是需要使用“""”將文件名引用起來;當集合爲一個或多個字符串時,必須使用“""”將字符串引用起來,則執行過程將會對每一個字符串進行一一處理;當集合類型爲一個命令行語句時,命令行語句需要使用“''”括起來,則會對該命令行的響應輸出信息進行處理。例如:

1
2
3
4
5
6
@echo off
for /f %%i in ('echo HelloWorld!'do (
  set myvar=%%i
)
echo myvar=%myvar%
pause > nul

這個例子就是變量“echo HelloWorld!”命令語句的輸出信息。

   下面再來看看“操作選項”,這裏的操作選項必須使用“""”括起來,可以包含一個處理選項或多個處理選項,多個處理選項之間使用空格符號進行分開,處理選項在該用法中是可選的。如果處理選項不存在,則臨時變量表示的是每一個文件或字符串或命令輸出的一行內容,這一行內容以空白符進行截斷;如果處理選項存在,則臨時變量表示的是每一個文件或字符串或命令輸出的一行內容中符號條件的部分內容。處理選項包括一下幾種(是一種子命令的方式):

選項表達式 說明 舉例
eol=c 指定忽略以“c”指定的字符開頭的元素,只能是單個字符(如果集合爲文件則指忽略以“c”開頭的行) eol=a(忽略a開頭的行)
skip=n 指定忽略的元素數n,以第一個元素開始,只能爲正整數(如果集合爲文件則指跳過0-n行) skip=3(忽略前3行)
delims=xxx 指定以“xxx”作爲元素的界定符號,默認以空格符或換行符作爲元素界定符號。可以包括多個字符,某一元素從第一個字符開始算起包含其中的某一個字符則視爲終止,其後的字符將被忽略(如果集合爲文件則指以“xxx”作爲行的界定符號) delims=。(使用“。”作爲換行符)
tokens=x,y,m-n 表示取到每一個元素的第x字符賦值給臨時變量,取第y個字符賦值給當前臨時變量字母的下一個字母變量,取第m到n個字符組成的字符串賦值給下一個字母變量,一共可以有26個取值。可以使用通配符,*表示所有,?表示單個任意字符 tokens=2表示取每一行的第二個字符;2,3表示取每一行的第二個和第三個字符;2-8表示取每一行第二個到第八個字符組成的字符串
usebackq 用於標記引號("")或('')中的爲文件名或命令行 usebackq

上面列表所列的是“/F”選項下的所有操作選項說明,這些選項只有在“/F”選項下纔可以使用。廢話不多說了,看下面的例子:

1
2
3
@echo off
for /f "delims=." %%i in ("a.txt"do echo %%i
pause > nul

這段代碼是將“a.txt”元素作爲字符串進行處理,截取“.”之前的字符並打印,保存爲批處理文件並執行即可看到效果。如果我也要將“a.txt”作爲文件名則可以在操作選項中加入“usebackq”選項。

   “for”語句的“/F”選項擴展主要用於內容的循環查找操作,在查找過程中對應的臨時變量的操作存在一個特殊的擴展處理方式——自動變量擴展,比如說當使用tokens操作選項來取得每一個元素或每一行的某個或幾個字符時,可以自動以當前定義臨時變量名(單獨字母字符)爲起點進行後續擴充,定義的臨時變量保存取得的第一類字符信息,下一個字符擴展的臨時變量則表示第二類字符信息,依次類推,規定最多隻能擴充26個臨時變量(包括當前變量在內),是由於tokens選項最多隻能指定26個值集合。來看下面的例子:

1
2
3
4
5
6
@echo off
cd C:\test
for /f "skip=2 tokens=2,3* delims= " %%a in ('dir'do (
  echo %%a--%%b--%%c
)
pause>nul

這個例子是將“DIR”命令的輸出信息作爲遍歷內容,首先跳過前兩行,然後從第三個字符塊開始取值,使用默認的方式進行換行或截斷操作,其中第二個字符塊將作爲“%%a”的值,第三個字節塊作爲“%%b”的值,第三個之後的字節塊作爲“%%c”的值。(目前我還沒找到什麼特殊的規律,這個值只能靠查看結果才能知道所表示的內容是什麼,臨時變量擴展雖然很方便但是使用需要謹慎,如果沒有取到值則會輸出“%變量名”信息,我並沒有很深入的去了解它,如果你有興趣,可以深入瞭解並整理一下結論和規律分享給大家)

2.12.goto/:——跳轉語句

   “goto”從字面上理解就是跳轉的意思,“goto”語句就是批處理中提供的流程跳轉語句,何爲流程跳轉?首先批處理的執行過程是自上而下順序執行的,默認情況下,批處理文件中的所有語句都會執行,不論上一條語句是否執行成功。如果在執行過程中遇到某種情況需要進行特殊處理,那麼就需要改變執行的流程,不過可以使用“if”語句來實現流程的控制,從理論上也可以實現跳過部分語句代碼的過程,但是比較麻煩,需要使用“if”語句塊來實現,所以批處理提供了“goto”語句來實現標籤式流程跳轉。標籤式跳轉也就是說首先要定義一個標記,然後使用“goto 標籤”的方式跳轉到指定的標籤語句塊內,所以“goto”語句必須結合標籤實現執行流程的跳轉,在批處理中使用“:”來聲明標籤,來看標籤和“goto”語句的基本用法:

goto [:]標籤名


: 標籤名

 命令行

批處理中規定,“goto”語句用於標籤式跳轉,其後緊接要跳轉到的標籤名稱(中間使用空白符分割);標籤的聲明必須使用“:”作爲前綴,也就是說在批處理中以“:”開頭的字符串或語句都是標籤,其標籤後的命令行語句是該標籤的標籤體,只要沒有遇到“goto”跳轉語句則其後的語句都會執行;其實標籤體是一個模糊的概念,很多情況下它是混淆的。看下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
@echo off
echo 準備跳轉到a標籤
goto a
echo 跳轉到a標籤後的語句
:a
echo 已經進入a標籤
:b
echo 已經進入b標籤
goto end
:end
echo 已經進入eof標籤
pause

上面的例子,從語法上看,定義有“a”標籤、“b”標籤和“end”標籤,從執行流程上看,“a”標籤和“b”標籤是混淆的,因爲缺少標籤結束語句,所以在使用標籤跳轉的時候一定要爲標籤體定義一個“goto”語句,表示跳出標籤體,如果是最後一個標籤則可以忽略。

   使用“goto”必須注意,標籤體在必要的時候必須使用“goto”跳轉語句進行終結,否則其後的所有標籤或非標籤都會作爲當前標籤的標籤體進行執行,正如上例一樣;其次還需要注意標籤結束時的“goto”跳轉語句,如果沒有需要,最好不要跳轉到當前標籤,否則會構成“死循環”,不斷的執行當前代碼體,理論上是無法退出的。看先一個的例子:

1
2
3
4
5
@echo off
:start
echo an infinite loop
goto start
pause

從執行流程上分析,這段代碼首先進入“start”標籤,然後跳轉到“start”標籤,然後在進入“start”標籤……從而構成了一個“封閉的迴路”,會無窮的執行下去(這只是理論上的猜想,實際上當達到某一個次數後會自動停止)。因此沒有必要這種寫法是不可取的。最後,再來看一個例子,使用“if”和“goto”實現的簡單計算器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@echo off
rem goto 語句練習,根據輸入內容跳轉到不同的標記位置
:start
set /p num1=輸入第一個數:
set /p num2=輸入第二個數:
set /p op=選擇操作符:1.加法 2.減法 3.乘法 4.除法
if %op% == 1 goto add
if %op% == 2 goto sub
if %op% == 3 goto mul
if %op% == 4 goto div
if %op% == "" goto :eof
:add
set /a result=%num1%+%num2%
echo %num1%+%num2%=%result%
goto end
:sub
set /a result=%num1%-%num2%
echo %num1%-%num2%=%result%
goto end
:mul
set /a result=%num1%*%num2%
echo %num1%*%num2%=%result%
goto end
:div
set /a result=%num1%/%num2%
echo %num1%/%num2%=%result%
goto end
:end
set /p choose=是否退出? (Y/N):
if /i %choose% equ y (
  exit
else (
  goto start
)

   上面的例子中使用了一個“goto :eof”語句,從運行的流程上看,如果沒有選擇則會跳轉到“eof”標籤,從結果上看,實質是退出了批處理文件,爲什麼呢?因爲“eof”標籤是批處理中的默認標籤,用於跳轉到批處理文件的末尾,也就是最後一條語句的後,所以會直接退出批處理文件。這個地方不能直接使用“goto eof”,因爲這樣會默認將“eof”作爲自定義標籤進行處理,只能使用“goto :eof”方式。

2.13.start——批處理啓動

“start”的字面意思是“啓動”,無可異議在批處理中是用於啓動程序的。“start”命令比較獨特,可以啓動人任意的程序或文件,只需要指定程序或文件的名稱即可,可以是全名稱(如果不指定擴展名會按照環境變量自行查找匹配),執行跨磁盤的程序啓動。其實“start”命令是一個啓動程序的入口,用法如下:

start ["title"] [/I] [/MIN] [/MAX] [/B] [command/program] [parameters]

其實“start”命令提供的選項操作比較多,可以通過“start/?”或“help start”命令查看,上面列出的是幾個常見的選項操作。其中“command/program”表示命令或程序名稱,“parameters”表示參數。

   “start”命令主要用於啓動批處理程序,可以啓動當前批處理程序外的其他批處理文件,例如使用“start C:\test.bat”可以啓動C盤下的test.bat批處理程序並在新的MS-DOS解釋器中執行,通俗一點的說就是在一個新窗口中打開並執行test.bat批處理程序。實質上“start”命令是以批處理文件默認關聯程序打開指定的文件,當然可以使用“title”選項來指定新窗口的標題,使用“/i”選項強制去掉引用舊窗口的環境變量,使用“/min”或“/max”選項指定新窗口是否最小化或最大化,使用“/b”選項強制進行窗口合併等,更多選項說明可以自行查閱。

   同時“start”命令還可以啓動其它程序,包括可執行程序以及文件等,但是可能不會提供更多的選項操作。同樣的道理,“start”命令是以要打開的程序所關聯的默認執行程序打開當前程序或文件的。瞭解Windows系統應該知道文件關聯選項中的一些設置,其實文件都是通過命令語句打開的。

2.14.call——批處理調用

   “call”的字面意思是“調用”,在批處理中“call”命令用於實現批處理文件的調用操作,事實上它不僅能實現批處理文件的調用,還可以實現標籤式調用,標籤式調用與“goto”的用法非常相識。“call”命令的用法如下:

call 批處理文件路徑 | :標籤名 [參數]

“call”命令可以在當前批處理文件中調動另一個批處理文件,也可以在當前批處理文件中調用某個聲明式標籤,從作用可以知道“call”共兼了“start”和“goto”的作用,其實還是存在一定的區別的。

   首先來介紹一下“call”命令調用批處理程序文件,使用“call”語句調用批處理程序與“start”命令啓動批處理程序非常類似,只需要指定批處理文件完全邏輯名稱或相對路徑名稱即可,例如“call test.bat”語句既可以執行test.bat批處理文件。細心的你可以會發現執行的批處理文件並不會開啓新的解釋執行窗口,然後會將被調用的批處理的所有輸出顯示語句都打印在當前窗口,換句話說就是被調用的批處理程序繼承了當前批處理程序的執行環境,然後先退出被調用的批處理程序,最後在退出當前批處理程序,這就是“call”語句與“start”命令的最大區別,“call”的這個功能很類是“start /b”命令,還一個區別是“call”命令沒有提供跟多的操作選項,但是可以在“call”語句後面拼接執行新程序時需要的參數(多個參數使用空白分割)。可以看下面的例子:

1
2
3
@echo off
call test.bat test
pause

其中“test.bat”的內容如下:

1
2
3
@echo off
echo %0----%1
pause > nul

從這個簡單的例子可以看成“call”命令的執行過程。其次“call”命令也具有調用其他可執行程序功能,與“start”命令使用一樣。

   下面看一下“call”命令標籤跳轉用法,使用“call”語句實現標籤跳轉語句與“goto”語句的用法非常類似,只需要在“call”命令後緊接要跳轉的標籤名稱即可,唯一不同的是這裏的標籤名稱需要指定“:”前綴,同樣可以在標籤名稱後拼接多個執行參數,看下面的例子:

1
2
3
4
5
6
7
8
@echo off
call :lable aaa "b b"
pause
:lable
echo firstParam=%0
echo secondParam=%1
echo thirdParam=%2
pause

這個例子可以說明“call”語句不僅能實現“goto”語句的功能,同時還可以傳遞參數。實際上“call”命令調用預先定義的標籤時,會將標籤語句視爲一個批處理程序集進行執行,執行完該標籤的所有語句後會再次返回到“call”語句後繼續執行,這也是“call”標籤跳轉與“goto”標籤跳轉的另一個區別,“goto”標籤跳轉後會繼續向標籤後執行,不會自動返回到“goto”語句後。通常情況下,使用“call”命令來調用標籤語句時,標籤體的末尾應該使用一個“goto :eof”語句來結束標籤體,當然也可以使用其他的語句,這樣做是爲了可以編寫多個“call”調用的標籤體語句,避免混淆。

   其次來看看關於“call”語句傳遞參數後如何訪問,在之前介紹“%”的時候介紹過“%num”(0=<num<=9)方式可以用來引用某些特殊命令語句傳入的參數,其中“num”表示參數的索引,從“0”開始,所以上面我們使用“%0”、“%1”、“%2”的方式來引用“call”傳遞的參數信息。(後面會繼續介紹)

2.15.cmd——啓動MS-DOS新窗口

   “cmd”命令,我想學過電腦的人應該都知道,“cmd”實質是“command(命令)”的縮寫,用於啓動一個MS-DOS命令行解釋器窗口,準確的說是啓動一個MS-DOS(cmd.exe應用程序)的一個新實例。我們大多數是在運行窗口“cmd”命令來啓動一個命令行窗口,其實“cmd”命令還提供了很多操作選項用來設置當前MS-DOS解釋器的環境變量。例如可以使用“/T:fg”設置當前命令行的前景(“f”)/背景(“g”)顏色(顏色值請參考“color”命令);使用“/E:ON”(“/X”)或者“/E:OFF”(“/Y”)啓用或停用命令擴展功能,默認情況下是啓動的;可以使用“/V:ON”或“/V:OFF”啓動或停用延遲環境變量擴展功能,用“setlocal”具有一樣的作用。而且“cmd”命令還可以將一句字符串作爲命令行語句進行解釋執行,用法如下:

cmd /S | /C | /K 字符串

其中字符串必須使用“""”引用,“/S”選項用於保留字符串的“""”並進行執行;“/C”或“/K”選項用於將“""”內部的字符串作爲命令語句進行解釋執行。需要注意的是“/S”選項不能與“/C”或“/K”選項一起使用,而且如果字符串語句是多條命令語句需要使用“&&”符號進行分割。

2.16.path——執行環境路徑管理

   “path”是Windows中比較重要的一個東西,在MS-DOS系統中同樣提供了“path”命令來定義當前批處理程序的資源路徑信息。當需要在批處理程序中調用某一個文件是必須先進入該文件所在的目錄,然後才能使用該資源;如果要引用另一個資源必須首選進入其所在的目錄(當然你也可以使用完全絕對路徑引用),顯然這種模式比較笨拙,我們可以首選使用“path”命令指定當前批處理工作所需的所有目錄,然後就可以在程序中直接引用資源名稱了,既可以減少相應的代碼量,也可以是程序更美觀。“path”命令的用法如下:

path 目錄完全路徑[;...][;%PATH%]

path [;]

使用“path”命令可以可以查看當前批處理程序或MS-DOS解釋器的執行目錄路徑;使用“path ;”命令可以將當前執行路徑置爲空;使用“path dirs”可以設置當前執行路徑,其中“dirs”可以爲一個目錄,也可以爲多個目錄,多個目錄需要使用“;”分割,同時還可以在原有的執行路徑上進行路徑擴展,可以使用內置環境變量“%path%”來引用原有目錄。

   “path”命令設置後,當程序中某個地方引用到某個資源名稱,則會在“path”指定的工作目錄中進行資源的查找,如果查找到了則引用,否則會導致錯誤。

2.17.exit——退出MS-DOS

   “exit”命令在之前已經介紹過,這裏在作一個簡單的補充說明。“exit”命令在MS-DOS解釋器用於退出當前“cmd.exe”程序,在批處理文件中用於退出並結束當前批處理程序,同時還可以擴展爲結束某個進程。用法格式爲:

exit [/B] [exitCode]

無參數的“exit”命令用於退出並結束當前命令行程序;“/B”選項用於強制指定當前退出的是批處理腳本程序而不是“cmd.exe”程序,如果在批處理教程外使用則用於退出“cmd.exe”程序;“exitCode”是一個代碼信息,不能與“/B”選項一起使用,代碼表示要退出的進程的ID值。

後記

   本篇主要介紹了批處理程序中的內置環境變量,流程控制語句等批處理中常見的命令,包括“IF”、“FOR”、“GOTO”等語句,當然還有其他的不怎麼常用的語句和命令等待着大家自行去發掘。介紹的內容可能並不一定全面,希望能諒解。

   梳理知識,分享大家,互利你我!怕拍板磚,就不知道自己整理的對知識掌握的問題所在,找到問題纔有所進步,歡迎大家踊躍的拍磚...

本文出自 “阿酷呆” 博客,請務必保留此出處http://akudy.blog.51cto.com/2277883/1257596


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章