DOS 批處理命令For迴圈命令詳解

lizhenqing發表於2017-12-29
轉載地址:

for命令是一種對一系列物件依次迴圈執行同一個或多個命令的在命令列或批處理中執行的命令,結合一些Windows管理中的程式後,其處理功能強大、應用靈活方便程度令人刮目相看。但是,其幫助資訊也因此複雜往往令初學者望而生畏,這裡根據本人的學習理解,把其用法分解簡化,疏忽和錯誤也許在所難免。

基本格式

(這裡寫的是在命令列裡用的格式,如果是在批處理中,需要把其中%再多加個%形成%%):

for /引數 %變數 in (集) do 命令

(注:上面除中文的以外,其餘的是按它的格式要求書寫的,大小寫都行)
引數:FOR分四種引數 D L R F,並且有的引數還可附加另外的選項下面會分別介紹
變數:(記住如果是在批處理中使用for命令時,變數前的%需改為%%)這個變數名是由單個字母組成且區分大小寫(原幫助是這麼說的,實際運用中用單個數字作為變數名試過證明也可行),如%B和%b代表的是不同的變數。
FOR命令會在每次迴圈中,把in (集)中讀取到的值賦於這個變數,以便其後的命令中引用。
集:由系列檔案、字串或由命令產生的內容形成的集合(當然可用萬用字元 * ?,還可引用環境變數),FOR命令是按一定順序和規律分次讀取集中內容,賦值給變數,並執行do後的命令,進行迴圈下一輪,直至集中內容讀取完畢,而括號是格式必須的(in到後面括號之間要有空格)。
命令:可以是任何合格的DOS命令或外部可被DOS呼叫的程式,且可採用括號把多條命令括起來,在一次迴圈中執行。
附註:由於一些目錄或檔名可能會有空格,所以很多時候集裡和命令裡往往需要用英文引號括起來(但有時引號裡的內容可能會被認為是字串)表示是一整體,下面開始的有些例中為簡捷起見,忽略檔名或目錄名帶空格這種情況。
現在按引數分類舉例解釋其用法:

一、引數 /d
for /d %%變數 in (集) do 命令
/d 引數是指定僅對目錄而不是檔案執行的for命令。
例1:
在命令列輸入(不是在批處理,之後不再解釋)
for /d %a in (c:\*.*) do echo %a
執行會把C盤根目錄下的全部目錄分次顯示出來,而不顯示檔名
看起來有點亂,如果把命令提示回顯關閉就清晰了:
for /d %a in (c:\*.*) do @echo %a


二、引數 /R
/R引數之後還可帶磁碟機代號及路徑
for /r 此處可以帶有路徑 %變數 in (集) do 命令
在/r 之後的那個路徑,指包含它之下的整個目錄樹(相當於DOS命令tree裡的範圍)中的所有目錄,如果僅為一個英文句點 . ,是指當前路徑下的目錄樹,如果省略了路徑則特指當前目錄,而之後的in (集)則相當於與前面每個目錄相配的檔案集
這裡按in(集)中有無萬用字元分兩種情況
1) in(集)中沒有萬用字元
指定的是單個檔案或列舉的具體檔案(多個檔名之間用分隔符分隔,如空格、逗號等)
例2

1
2
3
@echo of
for /r . %i in (abc.txt) do echo. > %i
echo on

注:這裡for /r 後的路徑僅有一個 . 而後面每個迴圈中echo. > %i相當於建立一個僅有一空行的文字檔案,整體效果是在當前目錄下包括子錄,每個目錄中建一個abc.txt。
例3 (放入批處理中)

1
2
3
4
@echo off
rem 顯示d:盤中所有檔名為file1和file2的列表
for /r d:\ %%h in (file1,file2) do if exist %%h echo %%h
pause


2) in(集)中含有萬用字元*或?
這種裡面的do命令將處理前面 /r指定的目錄系列裡每個含有in(集)中檔案的項,而不去理會不含有相配檔案的那些目錄
例4:

1
2
3
4
@echo off
rem 刪除C盤中所有*.chk的檔案
for /r c:\ %%h in (*.chk) do del /q %%h
pause


注:del /q 表示用安靜模式刪除(不需確認)

三、引數 /L
for /L %%變數 in (起始值,每次增值,結束時的比較值) do 命令
(上面L也可用小寫,主要為了視覺上不與數字1混淆而沒用小寫)
(起始值,每次增值,結束時的比較值)相當於一個等差數字序列,從“起始值”的數字開始,每次增加多少(也可設定為負數)為“每次增值”,並與“結束時的比較值”比較,超出則退出for迴圈(也不執行本輪後面的do 命令)
例如 (1,1,3) 將產生序列 (1 2 3);(1,2,9)將產生序列(1 3 5 7 9);(5,-1,1) 將產生序列 (5 4 3 2 1);(1,3,18)將產生序列(1 7 10 13 16)
例5

1
2
3
4
@echo off
::在D盤建立aa1~ aa5五個資料夾
for /L %%i in (1,1,5) do md d:\aa %%i
pause


注:在行首,單個冒號:接一名稱,是標號行,對應於批處理中go後指向的位置,而雙冒號::一般是用來作註釋用,註釋在批處理中可以用rem加空格來表達,二者稍有不同,rem註釋在未關閉命令回顯時會在螢幕顯示出來,而::則什麼情況下都不會顯示。


四、引數 /f
這個引數/f將會開啟(集)裡的檔案,使for命令能處理文字檔案的讀取和新增刪除替換等編輯性的操作,可謂功能強大,因此也相對複雜一些。
檔名-集
for /f “選項” %變數 in ( “字串”-集 ) do 命令
‘命令'-集
/f 後可以帶有幾種選項,不帶選項當然也是合格的格式,而帶有引數則必須以引號整體括起來,後面的集裡主要由三種形式形成的,最終在for迴圈中的每一輪中會形成讀取一行字串,來給指定的%變數、以及給由於選項中派生出附加變數賦值後,執行do後面的命令
下面以例子來具體說明和逐步理解各分項的用法
例6
假定d:\abc.txt內容如下:
姓名 性別 年齡 等-級
張三 男 36 A-1
李四 男 29 B-2
趙六 女 31 A-2


執行如下命令:
for /f %c in (d:\abc.txt) do @echo %c
則螢幕上顯示:
姓名
張三
李四
趙六


解釋:這是for /r 在“%變數”前預設引數選項時的情況,迴圈中每輪會預設以空格為分隔,在開啟的檔案中逐行給字串分段,又因為沒給增添附加變數(即僅一個變數%c)則僅把第一段的字元賦給%c,再執行 do後的命令,然後進行迴圈的下一輪,並且預設忽略空行
改一下:
for /f “skip=1 tokens=1,4 delims= ” %c in (d:\abc.txt) do @echo %c %d
顯示為:
張三 A-1
李四 B-2
趙六 A-2


解:
skip=1 表示文字開始忽略的行數為1 ——忽略幾行
delims= 在一行中,用什麼單個符號(可以有多字元組合,之間也不能加空格,被理解為多項單個字元,如要空格符須放最後)來分隔字串作為讀取賦值的單元(形成一段),本例中等號後是空的表示僅用空格來分隔。——用什麼刀來切分
tokens=1,4 這個等號後的數字表示依次取第幾個被分隔的字串段,來分別賦給%變數及順序附加的變數,本例取第1個段賦給%c,第4個段賦給c後的一個變數也就是賦給%d,並且,可以寫成tokens=1,2,5-7 或tokens=1,2,3* 或tokens=1,2,5,7 分別表示取第1,2,5,6,7(依次賦給%c, %d, %e, %,f, %g共5個變數)、1,2,3及3後的所有段(要賦給3個變數)、1,2,5,7(要賦給4個變數),tokens=後的數字號可以不按順序,但書寫的順序與分配給變數的順序是對應的,這是賦值,至於之後do命令中用不用是另一回事。換句話 --——最多隻需取哪幾段
in (變數) 中的那個變數,代表起始的一個變數名,按tokens中定義的總個數來擴充附加變數名,如總個數為3,則%c 就附加%d和%e ,要是%C就附加%D%E… 本例中tokens=1,4僅需兩個,起始的是in () 括號中的%c 則每行中第一段賦給%c,第4段賦給變數%d
以第二行(第一行被skip=1跳過了)為例,在 “張三 男 36 A-1 ” 中(正好也是用的空格分隔)共被空格之刀切為五段,只要第1、4,即張三賦給%c, A-1賦給%d,執行@echo %c %d然後下一輪…而空行照舊被省去了。


再稍改一下:


for /f “skip=1 tokens=4,1 delims=- “ %c in (d:\abc.txt) do @echo %c %d


則顯示為:
A 張三
B 李四
A 趙六


例7
假定d:\aa.txt內容如下:


Volume in drive D is MYDA
Volume Serial Number is C35D-8998


Directory of D:tmp


09/25/2001 10:40 AM 11,235 yg0925.txt
11/12/2001 04:29 pM 795 buple.txt
04/11/2002 04:18 AM 2,043 vitn.txt
3File(s) 12,673 bytes
0 Dir(s) 5,020,200,655 bytes free


在命令列輸入:
for /f "skip=5 tokens=5" %a in (d:\aa.txt) do @echo %a
會顯示:
yg0925.txt
buple.txt
vitn.txt
free
本意想把檔案裡列出的檔案顯示出來(當然也可以換成對檔案進行其他命令操作)
透過skip=5 忽略掉前5行,預設以空格分隔後tokens=5取每行第五段字元就順利地把檔名賦給變數%a,美中不足最後一行取了個不是檔名的(當然可用其他方法處理這個多餘的只是for/f中沒提供忽略最後幾行的格式),而倒數第二行則無第五段。
顯然例中aa.txt裡的內容是某次執行dir命令後的內容。它可用類似命令:
dir > d:\aa.txt來建立
題外話,如果在dir中加入合適的引數/b,就可以迴避多餘的部分,還可加入/ad只顯示目錄,加入/a-d只顯示檔案等
那麼,我們完全可以直接書寫命令放入in後的(‘命令'-集)中
for /f "skip=5 tokens=5 " %a in ('dir') do @echo %a


效果一樣。
注:命令集需用單引號括起來以表示不是檔案集,如用雙引號括起來則表示是字串集,本例是為了說明for命令的用法,真正有這種用途也願意用前面“題外話”的方法。如果你在執行本例後什麼也沒顯示,你需要先用集裡的命令先執行一次,看它顯示的格式,也許需要把tokens=5 改成tokens=4 或許還應當給dir加上引數 /a-d以迴避顯示出目錄。
如果集裡是由多個檔案組成,那麼處理完一個檔案後又處理完又去處理另一個檔案,每個檔案行數不同迴圈次數(do命令的次數)也將因此不同。
如果集裡是由命令產生的系統,那麼你必須首先熟悉該命令執行後會產生怎樣效果的字元系統,才能正確安排後面的do命令


畫龍點睛:無論in後的集是哪種形式,for/f 都最終分解為字串,按需要是否“忽略幾行”(skip=)、“用什麼刀來切分”(delims= )、“最多隻需取哪幾段”(tokens=)將集裡形成的字串,逐行地分段賦給%或%%後的變數及可能順延擴充套件出的變數,以執行do後的命令,每一行即為一輪迴圈。這裡沒完整說明全部引數,請在命令列用for/?檢視。(下面的斜體字是複製的幫助裡的內容)
例如:
對於帶有空格的檔名,您需要用雙引號將檔名括起來。為了用這種方式來使用雙引號,您還需要使用 usebackq 選項,否則,雙引號會被理解成是用作定義某個要分析的字串的。——換句話說,帶有usebackq(放在for /f 之後的引號裡)引數時 in ()裡用雙引號表示的仍是檔名。
還有一個選項eol= :前面所說skip=是表示忽略開始的幾行,其實預設狀況還忽略所有分號“ ; ”開始的行,如果你想不忽略分號開始的行,或者想忽略自己指定一字元開始的行就可以在for /f 之後那引號引數裡使用eol=你自己定義的字元,但它不像delims=的那樣可定義多個,只允許定義一個。


另一花樣:可以用 %~ 運算子將檔名分離成檔名、副檔名、磁碟機代號等獨立部分 ,請看for/?中的解釋(其中示例的變數為%I):
另外,FOR 變數參照的替換已被增強。您現在可以使用下列選項語法:


~I - 刪除任何引號("),擴充 %I
%~fI - 將 %I 擴充到一個完全合格的路徑名
%~dI - 僅將 %I 擴充到一個驅動器號
%~pI - 僅將 %I 擴充到一個路徑
%~nI - 僅將 %I 擴充到一個檔名
%~xI - 僅將 %I 擴充到一個副檔名
%~sI - 擴充的路徑只含有短名
%~aI - 將 %I 擴充到檔案的檔案屬性
%~tI - 將 %I 擴充到檔案的日期/時間
%~zI - 將 %I 擴充到檔案的大小
%~$PATH:I - 查詢列在路徑環境變數的目錄,並將 %I 擴充
到找到的第一個完全合格的名稱。如果環境變數名
未被定義,或者沒有找到檔案,此組合鍵會擴充到空字串


可以組合修飾符來得到多重結果:


%~dpI - 僅將 %I 擴充到一個驅動器號和路徑
%~nxI - 僅將 %I 擴充到一個檔名和副檔名
%~fsI - 僅將 %I 擴充到一個帶有短名的完整路徑名
%~dp$PATH:I - 查詢列在路徑環境變數的目錄,並將 %I 擴充
到找到的第一個驅動器號和路徑。
%~ftzaI - 將 %I 擴充到類似輸出線路的 DIR


簡記:凡是 %~ 打頭的運算子,都是檔名或環境變數的分離操作。而每項要想運用自如,則需要付出辛勤的練習。


練習:(我偷點懶,自己不作了...)
遍歷C、D盤,查詢已知檔名(接收鍵盤輸入),把其存放位置、時間,記錄到D:\mynote.txt 記錄格式如:


xx年xx月xx日 經查詢在C盤、D盤的xx檔案情況如下:
時間 位置
。。。。。 。。。。。。
。。。。。 。。。。。。
。。。。。 。。。。。。



提示:可能用到的DOS命令、變數、引數: echo、set 、set/p 、%date%、%~ >、>>


總結及提示:
for 命令的實際用法基本上已終結,但是僅此是不能寫出強大功能的批處理的,它只是一條DOS命令,需要熟練一些其他的DOS命令和Windows系統提供的命令,組合運用,才能充分發揮其強大、實用的功能,使得一些複雜事情,處理起來意想不到的簡潔方便。

附:常見在批處理for命令中需要的一個的命令或者叫環境設定:
for命令實際上是會作迴圈,如果在每輪的命令中改變某環境變數值,在預設狀態,一條for命令用%環境變數%只取一次值的,那麼下輪迴圈中再用時還是改變前的值(包括do後面帶有括號裡的多條命令的執行期間),就沒達到預期目的,為此,引入下面命令:
setlocal enabledelayedexpansion
開始批處理檔案中環境改動的本地化操作,並啟動延緩環境變數擴充套件。在執行SETLOCAL 達到批處理檔案結尾時,對於該批處理檔案的每個尚未執行的 setlocal 命令,都會有一個隱含的 endlocal 被執行。
在取變數值時,用!變數名!可以動態取值,延遲環境變數擴充允許您使用一個不同的字元(驚歎號)在執行時間擴充環境變數。這個用法實際是屬於在批處理中所有複合型命令都需要注意的。如果批處理結束後不希望將改變的環境保留,建議總是加上setlocal 。
要是結合一些其他複雜些的有關係統的、網路的命令(如wmic、net)進來,那才是方顯FOR英雄本色,比如遍歷本地磁碟可以用命令:wmic logicaldisk where "drivetype=3" get name 顯然要在所有磁碟裡查詢某檔案並作相應操作就很容易了,用好for命令也是需要其他命令和計算機基礎配合的。呵呵,本人水平有限,寫的只是低階層次的...但願能對有緣來這裡看的初學DOS的FOR命令者有所幫助。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29549873/viewspace-2149473/,如需轉載,請註明出處,否則將追究法律責任。

相關文章