---恢復內容開始---
終極dos批處理循環命令詳解 格式:FOR [參數] %%變量名 IN (相關文件或命令) DO 執行的命令 作用:對一個或一組文件,字符串或命令結果中的每一個對象執行特定命令,達到我們想要的結果。 注意:在批處理文件中使用 FOR 命令時,指定變量請使用 %%variable,而不要用 %variable。變量名稱是區分大小寫的,所以 %i 不同於 %I. 關於:for命令可以帶參數或不帶參數,帶參數時支持以下參數:/d /l /r /f 下面分別解釋一下 === 零:無參數時: --- FOR %variable IN (set) DO command [command-parameters] %variable 指定一個單一字母可替換的參數。 (set) 指定一個或一組文件。可以使用通配符。 command 指定對每個文件執行的命令。 command-parameters 為特定命令指定參數或命令行開關。 TTT示例: for %%i in (t*.*) do echo %%i --顯示當前目錄下與t*.*相匹配的文件(只顯示文件名,不顯示路徑) for %%i in (d:\mydocuments\*.doc) do @echo %%i --顯示d:\mydocuments\目錄下與*.doc相匹配的文件 === 一、參數 /d (參數只能顯示當前目錄下的目錄名字) --- 格式:FOR /D %variable IN (set) DO command [command-parameters] 這個參數主要用於目錄搜索,不會搜索文件,/D 參數只能顯示當前目錄下的目錄名字。(TTT特別說明:只會搜索指定目錄下的目錄,不會搜索再下一級的目錄。) TTT示例: for /d %%i in (c:\*) do echo %%i --顯示c盤根目錄下的所有目錄 for /d %%i in (???) do echo %%i --顯示當前目錄下名字只有1-3個字母的目錄 === 二、參數 /R (搜索指定路徑及所有子目錄中與set相符合的所有文件) --- 格式:FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters] 此命令會搜索指定路徑及所有子目錄中與set相符合的所有文件,注意是指定路徑及所有子目錄。 1、set中的文件名如果含有通配符(?或*),則列舉/R參數指定的目錄及其下面的所用子目錄中與set相符合的所有文件,無相符文件的目錄則不列舉。 2、如果set中為具體文件名,不含通配符,則枚舉該目錄樹(即列舉該目錄及其下面的所有子目錄)(並在后面加上具體的文件名),而不管set中的指定文件是否存在。 例:for /r c:\ %%i in (*.exe) do echo %%i --把C盤根目錄,和每個目錄的子目錄下面全部的EXE文件都列出來了!!!! TTT示例: for /r c:\ %%i in (boot.ini) do echo %%i --枚舉了c盤所有目錄 for /r d:\backup %%i in (1) do echo %%i --枚舉d\backup目錄 for /r c:\ %%i in (boot.ini) do if exist %%i echo %%i --很好的搜索命令,列舉boot.ini存在的目錄 === 三、參數 /L (該集表示以增量形式從開始到結束的一個數字序列。可以使用負的 Step) --- 格式:FOR /L %variable IN (start,step,end) DO command [command-parameters] 該集表示以增量形式從開始到結束的一個數字序列。可以使用負的 Step TTT示例: for /l %%i in (1,1,5) do @echo %%i --輸出1 2 3 4 5 for /l %%i in (1,2,10) do @echo %%i --輸出1,3,5,7,9 for /l %%i in (100,-20,1) do @echo %%i --輸出100,80,60,40,20 for /l %%i in (1,1,5) do start cmd --打開5個CMD窗口 for /l %%i in (1,1,5) do md %%i --建立從1~5共5個文件夾 for /l %%i in (1,1,5) do rd /q %%i --刪除從1~5共5個文件夾 四、參數 /F (使用文件解析來處理命令輸出、字符串及文件內容。) --- 這個參數是最難的,參數又多,先簡單的解釋一下:for命令帶這個參數可以分析文件內容,字符串內容或某一命令輸出的結果,並通過設置option得我們想要的結果。 以下是某高手的解釋,感覺有點太專業了,自認為不太容易理解,也列一下: [迭代及文件解析--使用文件解析來處理命令輸出、字符串及文件內容。使用迭代變量定義要檢查的內容或字符串,並使用各種options選項進一步修改解析方式。使用options令牌選項指定哪些令牌應該作為迭代變量傳遞。 請注意:在沒有使用令牌選項時,/F 將只檢查第一個令牌。文件解析過程包括讀取輸出、字符串或文件內容,將其分成獨立的文本行以及再將每行解析成零個或更多個令牌。然后通過設置為令牌的迭代變量值,調用 for 循環。 默認情況下,/F 傳遞每個文件每一行的第一個空白分隔符號。跳過空行。] +++ 格式: FOR /F ["options"] %variable IN (file-set) DO command [command-parameters] FOR /F ["options"] %variable IN ("string") DO command [command-parameters] FOR /F ["options"] %variable IN ('command') DO command [command-parameters] 或者,如果有 usebackq 選項: FOR /F ["options"] %variable IN (file-set) DO command [command-parameters] FOR /F ["options"] %variable IN ("string") DO command [command-parameters] FOR /F ["options"] %variable IN ('command') DO command [command-parameters] TTT說明:以上是WinXP系統中的幫助內容,你可以注意到,兩者完全相同,這其實是系統的錯誤,第二段“如果有 usebackq 選項:”應該以下的內容: FOR /F ["options"] %variable IN ("file-set") DO command [command-parameters] FOR /F ["options"] %variable IN ('string') DO command [command-parameters] FOR /F ["options"] %variable IN (`command`) DO command [command-parameters] --(`command`中的引號為反引號,是鍵盤上數字1左面的那個鍵) +++ (TTT說明:下面是詳細的解釋,大部分是系統中的幫助內容,也有些錯誤(怪不得for命令這么難學),已經被我糾正了。) 1) OPTION關鍵字詳解: eol=c:指一個行注釋字符的結尾(就一個)。例如:eol=; --忽略以分號打頭的那些行; skip=n:指在文件開始時忽略的行數。例如:skip=2 --忽略2行; delims=xxx:指分隔符集。這個替換了空格和跳格鍵的默認分隔符集。例如:[delims=, ] --指定用逗號,空格對字符串進行分隔。 tokens=x,y,m-n:指每行的哪一個符號被傳遞到每個迭代的 for 本身。這會導致額外變量名稱的分配。m-n格式為一個范圍。通過 nth 符號指定 mth。如果符號字符串中的最后一個字符是星號,那么額外的變量將在最后一個符號解析之后分配並接受行的保留文本。例如:tokens=2,3* --將每行中的第二個和第三個符號傳遞給 for 程序體;tokens=2,3* ... i% --將會把取到的第二個字符串賦給i%,第三個賦給j%,剩下的賦給k%。 關於usebackq,不同版本的系統提示不同的幫助,不過都有助於理解,所以都摘抄如下: (1),usebackq:使用后引號(鍵盤上數字1左面的那個鍵`)。未使用參數usebackq時:file-set表示文件,不能加引號,所以 不能含有空格;加雙引號表示字符串,即"string";加單引號表示執行命令,即'command'。使用參數usebackq時:file-set 和"file-set"都表示文件,當文件路徑或名稱中有空格時,就可以用雙引號括起來;單引號表示字符串,即'string';后引號表示命令執行,即 `command`。(此段是WinXP系統中的幫助) (2),usebackq:指定新語法已在下類情況中使用:在作為命令執行一個后引號的字符串;並且一個單引號字符為文字字符串命令;並允許在filenameset中使用雙引號擴起文件名稱。 以上兩條結合着看,其實已經可以明白了,我再說明一下: 其實這個參數的目的就是為了處理帶有空格的文件名。如果您要處理的文件名和路徑中含有空格,如果直接使用,會提示找不到文件。如果你用雙引號將文件名 和路徑括起來。這時候將作為字符串處理,而不是作為文件了。為了應對這種情況,所以才增加了這個“usebackq”參數。如果使用了這個參數,對於括號 中的加雙引號的集合,系統就可以認為是文件了;真正的字符串要加單引號;命令要加反引號。 2) file-set 為一個或多個文件名。繼續到 file-set 中的下一個文件之前,每份文件都已被打開、讀取並經過處理。處理包括讀取文件,將其分成一行行的文字,然后將每行解析成零或更多的符號。然后用已找到的符 號字符串變量值調用 For 循環。以默認方式,/F 通過每個文件的每一行中分開的第一個空白符號。跳過空白行。您可通過指定可選 "options"參數替代默認解析操作。這個帶引號的字符串包括一個或多個指定不同解析選項的關鍵字。 3) %i:專門在 for 語句中得到說明,%j 和 %k 是通過tokens= 選項專門得到說明的。您可以通過 tokens= 一行指定最多 26 個符號,只要不試圖說明一個高於字母 'z' 或'Z' 的變量。請記住,FOR 變量是單一字母、分大小寫和全局的;而且,同時不能有 52 個以上都在使用中。 (TTT補充說明: 一般在tokens后只指定第一個參數,如%%i或%%a,在后面使用第二個及兩個以上的參數,自動按順序往下排即可。如前面指定的是%%a,后面則 用%%b代表第二個結果,%%c代表第 三個結果。。。測試了一下tokens后指定多個變量名,沒有測試成功,應該是不可以的。所以token后只能跟要使用的第一個變量名 如果使用的變量名超過了%z或%Z,就無法使用了,曾經以為會循環過來:如%%z后可以使用%%a或%%A,但經測試,這是不可以的。 如:for /f "tokens=1,2,3* delims=-, " %%y in ("aa bb,cc-dd ee") do echo %%y %%z %%A %%a --只會輸出前兩個字符串,后面的兩個變量是無效的。) +++ 以下是系統提供的范例: FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k -- 說明:會分析 myfile.txt 中的每一行, eol=; --忽略以分號打頭的那些行; tokens=2,3* --將每行中的第二個和第三個符號傳遞給 for 程序體; delims= , --用逗號和/或空格定界符號。 %i --這個 for 程序體的語句引用 %i 來取得取得的首個字符串(本例中為第二個符號),引用 %j 來取得第二個字符串(本例中為第三個符號)引用 %k來取得第三個符號后的所有剩余符號。 (TTT說明:上述例子和說明中明顯的錯誤,%i應該換為%%i(幫助中有明確的說明:指定變量請使用 %%variable,而不要用 %variable,誤導) +++ TTT:下面列我做的幾個例子: 1,分析文件的例子 FOR /F "eol=; tokens=1,2* delims=,- " %%i in (d:\test.txt) do echo %%i %%j %%k 2,分析字符串的例子: for /f "tokens=1,2,3* delims=-, " %%i in ("aa bb,cc-dd ee") do echo %%i %%j %%k %%l 3,分析命令輸出的例子: FOR /F "tokens=1* delims==" %%i IN ('set') DO @echo [%%i----%%j] 如果使用了usebackq參數后,命令如下,結果與上面的完全相同。 1,分析文件的例子 FOR /F "usebackq eol=; tokens=1,2* delims=,- " %%i in ("d:\test.txt") do echo %%i %%j %%k 2,分析字符串的例子: for /f "usebackq tokens=1,2,3* delims=-, " %%i in ('aa bb,cc-dd ee') do echo %%i %%j %%k %%l 3,分析命令輸出的例子:(會枚舉當前環境中的環境變量名稱和值。) FOR /F "usebackq tokens=1* delims==" %%i IN (`set`) DO @echo [%%i----%%j] 結果大家可以試一下,很容易就明白的。 === FOR命令中的變量 --- FOR 變量參照的替換已被增強。您現在可以使用下列選項語法: ~I - 刪除任何引號("),擴充 %I %~fI - 將 %I 擴充到一個完全合格的路徑名 %~dI - 僅將 %I 擴充到一個驅動器號 %~pI - 僅將 %I 擴充到一個路徑 %~nI - 僅將 %I 擴充到一個文件名 %~xI - 僅將 %I 擴充到一個文件擴展名 %~sI - 擴充的路徑只含有短名 %~aI - 將 %I 擴充到文件的文件屬性 %~tI - 將 %I 擴充到文件的日期/時間 %~zI - 將 %I 擴充到文件的大小 %~$PATH:I - 查找列在路徑環境變量的目錄(TTT提示:是環境變量path的目錄),並將 %I 擴充到找到的第一個完全合格的名稱。如果環境變量名未被定義,或者沒有找到文件,此組合鍵會擴充到空字符串 此外,還可以組合修飾符來得到多重結果: %~dpI - 僅將 %I 擴充到一個驅動器號和路徑 %~nxI - 僅將 %I 擴充到一個文件名和擴展名 %~fsI - 僅將 %I 擴充到一個帶有短名的完整路徑名 %~dp$PATH:i - 查找列在路徑環境變量的目錄,並將 %I 擴充到找到的第一個驅動器號和路徑。 %~ftzaI - 將 %I 擴充到類似輸出線路的 DIR 在以上例子中,%I 和 PATH 可用其他有效數值代替。%~ 語法用一個有效的 FOR 變量名終止。選取類似 %I 的大寫變量名比較易讀,而且避免與不分大小寫的組合鍵混淆。 (以上是系統幫助的內容) 我們可以看到每行都有一個大寫字母"I",這個I其實就是我們在FOR帶入的變量,例如: FOR /F "usebackq eol=; tokens=1,2* delims=,- " %%x in ("d:\test.txt") do echo %%x %%y %%z 這里我們就要把那個x,y,z改成%~fx,%~fy,%~fz。 +++ TTT特例:以下是我根據以上說明作的一個綜合的例子,可以直接復制到記事本里,保存為bat格式(c盤下任一目錄),運行后,可以直觀的看到擴展后的效果。 @echo off echo ---顯示"dir c:\boot.ini /b /ah" for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 不擴展變量 %%i for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~fI %%~fi --擴充到一個完全合格的路徑名 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~dI %%~di --僅將變量擴充到一個驅動器號 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~pI %%~pi --僅將變量擴充到一個路徑 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~nI %%~ni --僅將變量擴充到一個文件名 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~xI %%~xi --僅將變量擴充到一個文件擴展名 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~sI %%~si --擴充的路徑只含有短名 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~aI %%~ai --將變量擴充到文件的文件屬性 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~tI %%~ti --將變量擴充到文件的日期/時間 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~zI %%~zi --將變量擴充到文件的大小 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~$PATH:I %%~$PATH:i --查找列在路徑環境變量的目錄,並將變量擴充到找到的第一個完全合格的名稱 echo ---以下顯示組合修飾符來得到多重結果---: for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~dpI %%~dpi --僅將變量擴充到一個驅動器號和路徑 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~nxI %%~nxi --僅將變量擴充到一個文件名和擴展名 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~fsI %%~fsI --僅將變量擴充到一個帶有短名的完整路徑名 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~dp$PATH:I %%~dp$PATH:i --查找列在路徑環境變量的目錄,並將變量擴充到找到的第一個驅動器號和路徑 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~ftzaI %%~ftzai --將變量擴充到類似輸出線路的DIR echo. echo ---顯示"dir C:\WINDOWS\system32\notepad.exe /b" for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 不擴展變量 %%i for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~fI %%~fi --擴充到一個完全合格的路徑名 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~dI %%~di --僅將變量擴充到一個驅動器號 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~pI %%~pi --僅將變量擴充到一個路徑 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~nI %%~ni --僅將變量擴充到一個文件名 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~xI %%~xi --僅將變量擴充到一個文件擴展名 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~sI %%~si --擴充的路徑只含有短名 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~aI %%~ai --將變量擴充到文件的文件屬性 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~tI %%~ti --將變量擴充到文件的日期/時間 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~zI %%~zi --將變量擴充到文件的大小 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~$PATH:I %%~$PATH:i --查找列在路徑環境變量的目錄,並將變量擴充到找到的第一個完全合格的名稱 echo ---以下顯示組合修飾符來得到多重結果---: for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~dpI %%~dpi --僅將變量擴充到一個驅動器號和路徑 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~nxI %%~nxi --僅將變量擴充到一個文件名和擴展名 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~fsI %%~fsI --僅將變量擴充到一個帶有短名的完整路徑名 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~dp$PATH:I %%~dp$PATH:i --查找列在路徑環境變量的目錄,並將變量擴充到找到的第一個驅動器號和路徑 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~ftzaI %%~ftzai --將變量擴充到類似輸出線路的DIR Pause TTT說明: 1,以上命令中,%%~fsI無法顯示,估計是系統錯誤,因為%%~fI是擴充到一個完全合格的路徑名,%%~sI只含有短文件名,本身是相互矛盾的,所以出錯。不知是系統的錯誤還是在考我們~~ 2,以上命令如果保存在別的盤中,無法顯示正確的驅動器和路徑。 3,如果想要%%~dp$PATH:i正常顯示,要保證環境變量path中確實有這個路徑:C:\WINDOWS\system32。 下面依次說明一下: +++ 一、 ~I - 刪除任何引號("),擴展 %I --- 這個變量的作用就如他的說明,刪除引號! 刪除引號規則如下(BAT兄補充!): 1、若字符串首尾同時存在引號,則刪除首尾的引號; 2、若字符串尾不存在引號,則刪除字符串首的引號; 3、如果字符串中間存在引號,或者只在尾部存在引號,則不刪除。 龍卷風補充:無頭不刪,有頭連尾刪。 我們來看這個例子,首先建立臨時文件temp.txt,內容如下 "1111 "2222" 3333" "4444"44 "55"55"55 也可建立個BAT文件代碼如下: @echo off echo ^"1111>temp.txt echo "2222">>temp.txt echo 3333^">>temp.txt echo "4444"44>>temp.txt echo ^"55"55"55>>temp.txt rem 上面建立臨時文件,注意不成對的引號要加轉義字符^,重定向符號前不要留空格 FOR /F "delims=" %%i IN (temp.txt) DO echo %%~i pause del temp.txt 執行后,我們看CMD的回顯如下: 1111 #字符串前的引號被刪除了 2222 #字符串首尾的引號都被刪除了 3333" #字符串前無引號,后面的引號保留 4444"44 #字符串前面的引號刪除了,而中間的引號保留 55"55"55 #字符串前面的引號刪除了,而中間的引號保留 請按任意鍵繼續. . . 結果和之前temp.txt中的內容對比一下,我們會發現第1、2、5行的引號都消失了,這就是刪除引號~i的作用了! +++ 二、 %~fI - 將 %I 擴展到一個完全合格的路徑名 示例: 把代碼保存放在隨便哪個地方,我這里就放桌面吧. FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~fi pause 執行后顯示內容如下 C:\Documents and Settings\Administrator\桌面\test.bat C:\Documents and Settings\Administrator\桌面\test.vbs 當我把代碼中的 %%~fi直接改成%%i FOR /F "delims==" %%i IN ('dir /b') DO @echo %%i pause 執行后就會顯示以下內容: test.bat test.vbs 通過對比,我們很容易就看出沒有路徑了,這就是"將 %I 擴展到一個完全合格的路徑名"的作用,也就是如果%i變量的內容是一個文件名的話,他就會把這個文件所在的絕對路徑打印出來,而不只單單打印一個文件名,自己動手動實驗下就知道了! +++ 三、 %~dI - 僅將 %I 擴展到一個驅動器號 看例子: 代碼如下,我還是放到桌面執行! FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~di pause 執行后我CMD里顯示如下 C: C: 我桌面就兩個文件test.bat,test.vbs,%%~di作用是,如果變量%%i的內容是一個文件或者目錄名,他就會把他這文件或者目錄所在的盤符號打印出來! +++ 四、 %~pI - 僅將 %I 擴展到一個路徑 這個用法和上面一樣,他只打印路徑不打印文件名字 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~pi pause 我就不打結果了,大家自己復制代碼看結果吧,下面幾個都是這么個用法,代碼給出來,大家自己看結果吧! +++ 五、 %~nI - 僅將 %I 擴展到一個文件名 只打印文件名字 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~ni pause +++ 六、 %~xI - 僅將 %I 擴展到一個文件擴展名 只打印文件的擴展名 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~xi pause +++ 七、 %~sI - 擴展的路徑只含有短名 打印絕對短文件名 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~si pause +++ 八、 %~aI - 將 %I 擴展到文件的文件屬性 打印文件的屬性 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~ai pause +++ 九、 %~tI - 將 %I 擴展到文件的日期/時間 打印文件建立的日期 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~ti pause +++ 十、 %~zI - 將 %I 擴展到文件的大小 打印文件的大小 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~zi pause 龍卷風補充:上面例子中的"delims=="可以改為"delims=",即不要分隔符 +++ 十一、 %~$PATH:I - 查找列在路徑環境變量的目錄,並將 %I 擴展到找到的第一個完全合格的名稱。如果環境變量名未被定義,或者沒有找到文件,此組合鍵會擴展到空字符串 這是最后一個,和上面那些都不一樣,我單獨說說! 然后在把這些代碼保存為批處理,放在桌面。 @echo off FOR /F "delims=" %%i IN (“notepad.exe”) DO echo %%~$PATH:i pause 龍卷風補充:上面代碼顯示結果為C:\WINDOWS\system32\notepad.exe 他的意思就在PATH變量里指定的路徑里搜索notepad.exe文件,如果有notepad.exe則會把他所在絕對路徑打印出來,沒有就打印一個錯誤! (TTT說明,保存到桌面上,運行顯示結果為:系統找不到文件 “notepad.exe”。查看環境變量path中確實有這個路徑,不明原因!后來發現了,原來是中文引號的原因。 上面的命令應該寫成: FOR /F "delims=" %%i IN ("notepad.exe") DO echo %%~$PATH:i ) 最后發一個用批處理做一五子棋游戲: @echo off&setlocal enabledelayedexpansion mode con: lines=43 cols=110 set li39= A B C D E F G H I J K L M N O P Q R S set li0= ┌─────────────────────────────────────┐ set li1=A│┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐│A set var=1 for %%a in (!li39:~5^,-1!) do (set/a var+=2&set li!var!=%%a│├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤│%%a) for /l %%a in (2,2,36) do (set li%%a= ││ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ││) set li37=S│└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘│S set li38= └─────────────────────────────────────┘ set str=a b c d e f g h i j k l m n o p q r s for %%a in (%str%) do (set/a .+=1,%%a=.&set z!.!=%%a) set li5=!li5! 五 棋 子 人 機 對 戰 set li7=!li7! 批 處 理 set li10=!li10! 電 腦 水 平 中 等 set li31=!li31! 由 netbenton 編寫完成 set li33=!li33! 棋盤設計參照了 batman title 批處理五子棋 set str=################### set .=0 for /l %%a in (1,1,19) do ( set he%%a=!str!&set sh%%a=!str! for /l %%b in (1,1,19) do set [%%a.%%b=0 ) set .=33 for /l %%a in (5,1,19) do ( set pi%%a=!str:~,%%a!&set ni%%a=!str:~,%%a! set pi!.!=!str:~,%%a!&set ni!.!=!str:~,%%a! set/a .-=1 ) set ●=○&set ○=● set zhi=● set say=say ::設置電腦IQ set idea=@@@@#.1 #@@@@.5 @#@@@.4 @@@#@.2 @@#@@.3 vs0 #.1 # .5 .3 $# $#$.2 vs1#@@@##.2 ##@@@#.5 #@@#@#.3 #@#@@#.4 vs2 #@##@@#.4-5 #@@##@#.4-3 #@#@@.3-5 @#@@#.4-1 #@@@##.2-W-1##@@@#.5-W-6 vs3 set idea=!idea! ##@@@.4-W-5 @@@##.2-W-1 @##@@#.4-5 #@##@@.3-4 #@#@#@.4-2 @#@#@#.3-5 vs4 # #.4-W-1-6 ## $##.2-W-1-6 vs5 ##@@##.2-5-W-6-1 #@#@#.3-w-1-5 ## $##.W-2-1 .W-3-4 $# #$.W-2-5 ## ##.W-2-W-1-5 #$#$#.W-3-W-1-5 #$##$#.W-3-4 set idea=!idea! vs7 #$$$#.1-5 @@###.4-3 ###@@.3-4 ###@###.3-5-W-2-6-W-1-7 vs8 ###$###.3-5 vs9 @####.4 ####@.2 #$###.3 ###$#.3 set idea=!idea! ###@#.3 #@###.3 $####.3 ####$.3 .3 $#$##.2 ##$#$.4 #$##$.3 $##$#.3 $###$.3 vs10 set iqam=1000000000 :restart ( setlocal enabledelayedexpansion for /l %%a in (0,1,39) do (echo !li%%a!) set li39=!li39! reboot重新開始,exit退出。 set li37=!li37! back 悔棋 set /p var=選擇誰先下[ W,玩家 D,電腦 Q,退出 ]: if /i "!var!" equ "Q" goto :quit if /i "!var!" equ "D" (set onez=○&set towz=●&set hou=☆) else (set onez=●&set towz=○&set hou=★) set a!onez!=電腦&set a!towz!=玩家 ) ( set ttr=!idea=%onez%!&set ttr=!ttr=%towz%! set idea= for %%a in (!ttr!) do ( for /f "tokens=1,2 delims=." %%b in ("%%a") do (set %%b=%%c&set idea=!idea! %%b) ) set ttr= set li27=!li27! !onez! !a%onez%! set li25=!li25! !towz! !a%towz%! set/a pos=10,poh=10&goto :getok ) :loop (if %zhi% equ %onez% goto :men set .= setlocal enabledelayedexpansion for %%a in (!idea!) do ( set str=%%a if "!str:~,2!" neq "vs" ( for %%b in (he sh) do ( set all=!%%b1!!%%b2!!%%b3!!%%b4!!%%b5!!%%b6!!%%b7!!%%b8!!%%b9!!%%b10!!%%b11!!%%b12!!%%b13!!%%b14!!%%b15!!%%b16!!%%b17!!%%b18!!%%b19! if "!all:%%a=!" neq "!all!" ( for /l %%c in (1,1,19) do ( if "!%%b%%c:%%a=!" neq "!%%b%%c!" set/a .+=1&set put!.!=%%b %%c.%%a.!iqam! ) ) ) for %%b in (pi ni) do ( set all=!%%b5!!%%b6!!%%b7!!%%b8!!%%b9!!%%b10!!%%b11!!%%b12!!%%b13!!%%b14!!%%b15!!%%b16!!%%b17!!%%b18!!%%b19!!%%b20!!%%b21!!%%b22!!%%b23!!%%b24!!%%b25!!%%b26!!%%b27!!%%b28!!%%b29!!%%b30!!%%b31!!%%b32!!%%b33! if "!all:%%a=!" neq "!all!" ( for /l %%c in (5,1,33) do ( if "!%%b%%c:%%a=!" neq "!%%b%%c!" set/a .+=1&set put!.!=%%b %%c.%%a.!iqam! ) ) ) ) else ( set/a "iqam=(iqam+1)/8" if %%a equ vs8 if defined . goto :get if %%a equ vs9 if defined . goto :get ) )) if defined . (goto :get) echo. 已經和棋了 pause endlocal&goto :restart :men ( set/a .=lips-1&for /f "tokens=1-3" %%b in ("li!liph! !lips! !.!") do (set %%b=!%%b:~0,%%d!%hou%!%%b:~%%c!) set li38=!li38![%悔:~,24%] cls for /l %%a in (0,1,39) do (echo !li%%a!) for /f "tokens=1-3" %%b in ("li!liph! !lips! !.!") do (set %%b=!%%b:~0,%%d!%zhi%!%%b:~%%c!) set li38=%li38% set /p user=!say:say=%error%! [列前,行后]: if "!user!" equ "reboot" endlocal&goto :restart if "!user!" equ "exit" goto :quit if "!user!" equ "back" call :悔&goto :men set/a pos=!user:~0,1!,poh=!user:~1,2!,var=pos-1 2>nul if not defined [!poh!.!pos! set error=輸入點不存在 &goto :men ) if "!he%poh%:~%var%,1!" neq "#" set error=該點已經有子 &goto men goto :getok :get set `= ::取最佳的走法 for /l %%z in (!.!,-1,1) do ( for /f "tokens=1,2,3 delims=." %%1 in ("!put%%z!") do ( for /f "tokens=1-4" %%a in ("%%1 %%2") do ( set iqm=%%3 set vara=!%%a%%b:*%%c=!srqponmlkjihgfedcba0 for %%4 in (!%%2:-^=;!) do ( if "%%4" equ "W" (set/a iqm=iqm/5*3) else ( set/a var=!vara:~19,1!+%%4 if "%%a" equ "he" (set/a poh=%%b,pos=20-var) if "%%a" equ "sh" (set/a poh=20-var,pos=%%b) if %%b lss 19 (set/a var=%%b-var+1) else (set/a var=38-%%b-var+1) if "%%a" equ "pi" (if %%b lss 19 (set/a pos=var,poh=%%b-var+1) else (set/a poh=20-var,pos=%%b-19+var)) if "%%a" equ "ni" (if %%b lss 19 (set/a pos=var,poh=19-%%b+var) else (set/a poh=var,pos=%%b-19+var)) if not defined R!pos!R!poh!R set /a `+=1&set ram!`!=R!pos!R!poh!R set/a R!pos!R!poh!R+=iqm ) ) ) ) ) set rmk=0 for /l %%a in (1,1,!`!) do ( for %%b in (!ram%%a!) do ( for %%c in (!%%b!) do ( if %%c gtr !rmk! set/a rmk=%%c,.=0 if %%c equ !rmk! set rmz!.!=%%b&set/a .+=1 ) ) ) set/a .=!random!%%. for /f "tokens=1,2 delims=R" %%a in ("!rmz%.%!") do (set/a pos=%%a,poh=%%b) rem start set r^&echo !.!^&pause^&exit endlocal&set/a pos=%pos%,poh=%poh% set say=say !z%pos%!!z%poh%!(%poh%)&set error=電腦最后下在: :getok set zhi=!%zhi%!&set win=!zhi!!zhi!!zhi!!zhi!!zhi! (set/a piph=poh+pos-1,lips=pos*2+1,niph=19+pos-poh,liph=poh*2-1 if !piph! lss 19 (set/a pips=pos) else (set/a pips=20-poh) if !niph! lss 19 (set/a nips=pos) else (set/a nips=poh) for %%a in ("li!liph! !lips!" "he!poh! !pos!" "sh!pos! !poh!" "pi!piph! !pips!" "ni!niph! !nips!") do ( for /f "tokens=1,2" %%b in (%%a) do ( set/a .=%%c-1 for %%d in (!.!) do (set %%b=!%%b:~0,%%d!%zhi%!%%b:~%%c!) if "!%%b:%win%=!" neq "!%%b!" set win=y ) )) (set/a asc%zhi%+=1 set 悔= !z%pos%!!z%poh%!!悔! if !win! neq y goto :loop) for /l %%a in (0,1,39) do (echo !li%%a!) set/p= !a%zhi%! %zhi%子 第!asc%zhi%!手 !z%pos%!!z%poh%!(%poh%) 勝出 <nul pause endlocal&goto :restart :悔 if not defined 悔 goto :eof if "!悔:~6,1!" equ "" goto :eof for %%a in (!悔:~^,6!) do (set str=%%a set/a poh=!str:~-1!,pos=!str:~,1! set/a piph=poh+pos-1,niph=19+pos-poh,liph=poh*2-1,lips=pos*2+1 if !piph! lss 19 (set/a pips=pos) else (set/a pips=20-poh) if !niph! lss 19 (set/a nips=pos) else (set/a nips=poh) for %%a in ( "he!poh! !pos!" "sh!pos! !poh!" "pi!piph! !pips!" "ni!niph! !nips!") do ( for /f "tokens=1,2" %%b in (%%a) do ( set/a .=%%c-1 for %%d in (!.!) do (set %%b=!%%b:~0,%%d!#!%%b:~%%c!) ) ) for /f "tokens=1,2" %%b in ("li!liph! !lips!") do ( set/a .=%%c-1 for %%d in (!.!) do (set %%b=!%%b:~0,%%d!┼!%%b:~%%c!) )) set/a asc%zhi%-=1 set 悔=!悔:~6! set error=你悔棋,耍賴皮! if not defined 悔 goto :eof set/a poh=!悔:~2,1!,pos=!悔:~1,1!,liph=poh*2-1,lips=pos*2+1 set say=say !z%pos%!!z%poh%!(%poh%) goto :eof :quit taskkill /fi "WINDOWTITLE eq 批處理五子棋*" /im cmd.exe
終極dos批處理循環命令詳解格式:FOR [參數] %%變量名 IN (相關文件或命令) DO 執行的命令 作用:對一個或一組文件,字符串或命令結果中的每一個對象執行特定命令,達到我們想要的結果。 注意:在批處理文件中使用 FOR 命令時,指定變量請使用 %%variable,而不要用 %variable。變量名稱是區分大小寫的,所以 %i 不同於 %I. 關於:for命令可以帶參數或不帶參數,帶參數時支持以下參數:/d /l /r /f 下面分別解釋一下
=== 零:無參數時: --- FOR %variable IN (set) DO command [command-parameters] %variable 指定一個單一字母可替換的參數。 (set) 指定一個或一組文件。可以使用通配符。 command 指定對每個文件執行的命令。 command-parameters 為特定命令指定參數或命令行開關。
TTT示例: for %%i in (t*.*) do echo %%i --顯示當前目錄下與t*.*相匹配的文件(只顯示文件名,不顯示路徑) for %%i in (d:\mydocuments\*.doc) do @echo %%i --顯示d:\mydocuments\目錄下與*.doc相匹配的文件 === 一、參數 /d (參數只能顯示當前目錄下的目錄名字) --- 格式:FOR /D %variable IN (set) DO command [command-parameters] 這個參數主要用於目錄搜索,不會搜索文件,/D 參數只能顯示當前目錄下的目錄名字。(TTT特別說明:只會搜索指定目錄下的目錄,不會搜索再下一級的目錄。)
TTT示例: for /d %%i in (c:\*) do echo %%i --顯示c盤根目錄下的所有目錄 for /d %%i in (???) do echo %%i --顯示當前目錄下名字只有1-3個字母的目錄
=== 二、參數 /R (搜索指定路徑及所有子目錄中與set相符合的所有文件) --- 格式:FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters] 此命令會搜索指定路徑及所有子目錄中與set相符合的所有文件,注意是指定路徑及所有子目錄。
1、set中的文件名如果含有通配符(?或*),則列舉/R參數指定的目錄及其下面的所用子目錄中與set相符合的所有文件,無相符文件的目錄則不列舉。 2、如果set中為具體文件名,不含通配符,則枚舉該目錄樹(即列舉該目錄及其下面的所有子目錄)(並在后面加上具體的文件名),而不管set中的指定文件是否存在。 例:for /r c:\ %%i in (*.exe) do echo %%i --把C盤根目錄,和每個目錄的子目錄下面全部的EXE文件都列出來了!!!!
TTT示例: for /r c:\ %%i in (boot.ini) do echo %%i --枚舉了c盤所有目錄 for /r d:\backup %%i in (1) do echo %%i --枚舉d\backup目錄 for /r c:\ %%i in (boot.ini) do if exist %%i echo %%i --很好的搜索命令,列舉boot.ini存在的目錄
=== 三、參數 /L (該集表示以增量形式從開始到結束的一個數字序列。可以使用負的 Step) --- 格式:FOR /L %variable IN (start,step,end) DO command [command-parameters] 該集表示以增量形式從開始到結束的一個數字序列。可以使用負的 Step
TTT示例: for /l %%i in (1,1,5) do @echo %%i --輸出1 2 3 4 5 for /l %%i in (1,2,10) do @echo %%i --輸出1,3,5,7,9 for /l %%i in (100,-20,1) do @echo %%i --輸出100,80,60,40,20 for /l %%i in (1,1,5) do start cmd --打開5個CMD窗口 for /l %%i in (1,1,5) do md %%i --建立從1~5共5個文件夾 for /l %%i in (1,1,5) do rd /q %%i --刪除從1~5共5個文件夾
四、參數 /F (使用文件解析來處理命令輸出、字符串及文件內容。) --- 這個參數是最難的,參數又多,先簡單的解釋一下:for命令帶這個參數可以分析文件內容,字符串內容或某一命令輸出的結果,並通過設置option得我們想要的結果。 以下是某高手的解釋,感覺有點太專業了,自認為不太容易理解,也列一下: [迭代及文件解析--使用文件解析來處理命令輸出、字符串及文件內容。使用迭代變量定義要檢查的內容或字符串,並使用各種options選項進一步修改解析方式。使用options令牌選項指定哪些令牌應該作為迭代變量傳遞。 請注意:在沒有使用令牌選項時,/F 將只檢查第一個令牌。文件解析過程包括讀取輸出、字符串或文件內容,將其分成獨立的文本行以及再將每行解析成零個或更多個令牌。然后通過設置為令牌的迭代變量值,調用 for 循環。 默認情況下,/F 傳遞每個文件每一行的第一個空白分隔符號。跳過空行。] +++ 格式: FOR /F ["options"] %variable IN (file-set) DO command [command-parameters] FOR /F ["options"] %variable IN ("string") DO command [command-parameters] FOR /F ["options"] %variable IN ('command') DO command [command-parameters]
或者,如果有 usebackq 選項: FOR /F ["options"] %variable IN (file-set) DO command [command-parameters] FOR /F ["options"] %variable IN ("string") DO command [command-parameters] FOR /F ["options"] %variable IN ('command') DO command [command-parameters]
TTT說明:以上是WinXP系統中的幫助內容,你可以注意到,兩者完全相同,這其實是系統的錯誤,第二段“如果有 usebackq 選項:”應該以下的內容: FOR /F ["options"] %variable IN ("file-set") DO command [command-parameters] FOR /F ["options"] %variable IN ('string') DO command [command-parameters] FOR /F ["options"] %variable IN (`command`) DO command [command-parameters] --(`command`中的引號為反引號,是鍵盤上數字1左面的那個鍵)
+++ (TTT說明:下面是詳細的解釋,大部分是系統中的幫助內容,也有些錯誤(怪不得for命令這么難學),已經被我糾正了。)
1) OPTION關鍵字詳解: eol=c:指一個行注釋字符的結尾(就一個)。例如:eol=; --忽略以分號打頭的那些行; skip=n:指在文件開始時忽略的行數。例如:skip=2 --忽略2行; delims=xxx:指分隔符集。這個替換了空格和跳格鍵的默認分隔符集。例如:[delims=, ] --指定用逗號,空格對字符串進行分隔。 tokens=x,y,m-n:指每行的哪一個符號被傳遞到每個迭代的 for 本身。這會導致額外變量名稱的分配。m-n格式為一個范圍。通過 nth 符號指定 mth。如果符號字符串中的最后一個字符是星號,那么額外的變量將在最后一個符號解析之后分配並接受行的保留文本。例如:tokens=2,3* --將每行中的第二個和第三個符號傳遞給 for 程序體;tokens=2,3* ... i% --將會把取到的第二個字符串賦給i%,第三個賦給j%,剩下的賦給k%。 關於usebackq,不同版本的系統提示不同的幫助,不過都有助於理解,所以都摘抄如下: (1),usebackq:使用后引號(鍵盤上數字1左面的那個鍵`)。未使用參數usebackq時:file-set表示文件,不能加引號,所以 不能含有空格;加雙引號表示字符串,即"string";加單引號表示執行命令,即'command'。使用參數usebackq時:file-set 和"file-set"都表示文件,當文件路徑或名稱中有空格時,就可以用雙引號括起來;單引號表示字符串,即'string';后引號表示命令執行,即 `command`。(此段是WinXP系統中的幫助) (2),usebackq:指定新語法已在下類情況中使用:在作為命令執行一個后引號的字符串;並且一個單引號字符為文字字符串命令;並允許在filenameset中使用雙引號擴起文件名稱。 以上兩條結合着看,其實已經可以明白了,我再說明一下: 其實這個參數的目的就是為了處理帶有空格的文件名。如果您要處理的文件名和路徑中含有空格,如果直接使用,會提示找不到文件。如果你用雙引號將文件名 和路徑括起來。這時候將作為字符串處理,而不是作為文件了。為了應對這種情況,所以才增加了這個“usebackq”參數。如果使用了這個參數,對於括號 中的加雙引號的集合,系統就可以認為是文件了;真正的字符串要加單引號;命令要加反引號。
2) file-set 為一個或多個文件名。繼續到 file-set 中的下一個文件之前,每份文件都已被打開、讀取並經過處理。處理包括讀取文件,將其分成一行行的文字,然后將每行解析成零或更多的符號。然后用已找到的符 號字符串變量值調用 For 循環。以默認方式,/F 通過每個文件的每一行中分開的第一個空白符號。跳過空白行。您可通過指定可選 "options"參數替代默認解析操作。這個帶引號的字符串包括一個或多個指定不同解析選項的關鍵字。
3) %i:專門在 for 語句中得到說明,%j 和 %k 是通過tokens= 選項專門得到說明的。您可以通過 tokens= 一行指定最多 26 個符號,只要不試圖說明一個高於字母 'z' 或'Z' 的變量。請記住,FOR 變量是單一字母、分大小寫和全局的;而且,同時不能有 52 個以上都在使用中。 (TTT補充說明: 一般在tokens后只指定第一個參數,如%%i或%%a,在后面使用第二個及兩個以上的參數,自動按順序往下排即可。如前面指定的是%%a,后面則 用%%b代表第二個結果,%%c代表第 三個結果。。。測試了一下tokens后指定多個變量名,沒有測試成功,應該是不可以的。所以token后只能跟要使用的第一個變量名 如果使用的變量名超過了%z或%Z,就無法使用了,曾經以為會循環過來:如%%z后可以使用%%a或%%A,但經測試,這是不可以的。 如:for /f "tokens=1,2,3* delims=-, " %%y in ("aa bb,cc-dd ee") do echo %%y %%z %%A %%a --只會輸出前兩個字符串,后面的兩個變量是無效的。) +++ 以下是系統提供的范例: FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k -- 說明:會分析 myfile.txt 中的每一行, eol=; --忽略以分號打頭的那些行; tokens=2,3* --將每行中的第二個和第三個符號傳遞給 for 程序體; delims= , --用逗號和/或空格定界符號。 %i --這個 for 程序體的語句引用 %i 來取得取得的首個字符串(本例中為第二個符號),引用 %j 來取得第二個字符串(本例中為第三個符號)引用 %k來取得第三個符號后的所有剩余符號。 (TTT說明:上述例子和說明中明顯的錯誤,%i應該換為%%i(幫助中有明確的說明:指定變量請使用 %%variable,而不要用 %variable,誤導)
+++ TTT:下面列我做的幾個例子: 1,分析文件的例子 FOR /F "eol=; tokens=1,2* delims=,- " %%i in (d:\test.txt) do echo %%i %%j %%k 2,分析字符串的例子: for /f "tokens=1,2,3* delims=-, " %%i in ("aa bb,cc-dd ee") do echo %%i %%j %%k %%l 3,分析命令輸出的例子: FOR /F "tokens=1* delims==" %%i IN ('set') DO @echo [%%i----%%j]
如果使用了usebackq參數后,命令如下,結果與上面的完全相同。 1,分析文件的例子 FOR /F "usebackq eol=; tokens=1,2* delims=,- " %%i in ("d:\test.txt") do echo %%i %%j %%k 2,分析字符串的例子: for /f "usebackq tokens=1,2,3* delims=-, " %%i in ('aa bb,cc-dd ee') do echo %%i %%j %%k %%l 3,分析命令輸出的例子:(會枚舉當前環境中的環境變量名稱和值。) FOR /F "usebackq tokens=1* delims==" %%i IN (`set`) DO @echo [%%i----%%j] 結果大家可以試一下,很容易就明白的。 === FOR命令中的變量 --- FOR 變量參照的替換已被增強。您現在可以使用下列選項語法: ~I - 刪除任何引號("),擴充 %I %~fI - 將 %I 擴充到一個完全合格的路徑名 %~dI - 僅將 %I 擴充到一個驅動器號 %~pI - 僅將 %I 擴充到一個路徑 %~nI - 僅將 %I 擴充到一個文件名 %~xI - 僅將 %I 擴充到一個文件擴展名 %~sI - 擴充的路徑只含有短名 %~aI - 將 %I 擴充到文件的文件屬性 %~tI - 將 %I 擴充到文件的日期/時間 %~zI - 將 %I 擴充到文件的大小 %~$PATH:I - 查找列在路徑環境變量的目錄(TTT提示:是環境變量path的目錄),並將 %I 擴充到找到的第一個完全合格的名稱。如果環境變量名未被定義,或者沒有找到文件,此組合鍵會擴充到空字符串 此外,還可以組合修飾符來得到多重結果: %~dpI - 僅將 %I 擴充到一個驅動器號和路徑 %~nxI - 僅將 %I 擴充到一個文件名和擴展名 %~fsI - 僅將 %I 擴充到一個帶有短名的完整路徑名 %~dp$PATH:i - 查找列在路徑環境變量的目錄,並將 %I 擴充到找到的第一個驅動器號和路徑。 %~ftzaI - 將 %I 擴充到類似輸出線路的 DIR 在以上例子中,%I 和 PATH 可用其他有效數值代替。%~ 語法用一個有效的 FOR 變量名終止。選取類似 %I 的大寫變量名比較易讀,而且避免與不分大小寫的組合鍵混淆。
(以上是系統幫助的內容) 我們可以看到每行都有一個大寫字母"I",這個I其實就是我們在FOR帶入的變量,例如: FOR /F "usebackq eol=; tokens=1,2* delims=,- " %%x in ("d:\test.txt") do echo %%x %%y %%z 這里我們就要把那個x,y,z改成%~fx,%~fy,%~fz。
+++ TTT特例:以下是我根據以上說明作的一個綜合的例子,可以直接復制到記事本里,保存為bat格式(c盤下任一目錄),運行后,可以直觀的看到擴展后的效果。 @echo off echo ---顯示"dir c:\boot.ini /b /ah" for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 不擴展變量 %%i for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~fI %%~fi --擴充到一個完全合格的路徑名 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~dI %%~di --僅將變量擴充到一個驅動器號 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~pI %%~pi --僅將變量擴充到一個路徑 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~nI %%~ni --僅將變量擴充到一個文件名 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~xI %%~xi --僅將變量擴充到一個文件擴展名 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~sI %%~si --擴充的路徑只含有短名 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~aI %%~ai --將變量擴充到文件的文件屬性 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~tI %%~ti --將變量擴充到文件的日期/時間 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~zI %%~zi --將變量擴充到文件的大小 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~$PATH:I %%~$PATH:i --查找列在路徑環境變量的目錄,並將變量擴充到找到的第一個完全合格的名稱 echo ---以下顯示組合修飾符來得到多重結果---: for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~dpI %%~dpi --僅將變量擴充到一個驅動器號和路徑 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~nxI %%~nxi --僅將變量擴充到一個文件名和擴展名 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~fsI %%~fsI --僅將變量擴充到一個帶有短名的完整路徑名 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~dp$PATH:I %%~dp$PATH:i --查找列在路徑環境變量的目錄,並將變量擴充到找到的第一個驅動器號和路徑 for /f "delims==" %%i in ('dir c:\boot.ini /b /ah') do echo 擴展變量到~ftzaI %%~ftzai --將變量擴充到類似輸出線路的DIR echo. echo ---顯示"dir C:\WINDOWS\system32\notepad.exe /b" for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 不擴展變量 %%i for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~fI %%~fi --擴充到一個完全合格的路徑名 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~dI %%~di --僅將變量擴充到一個驅動器號 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~pI %%~pi --僅將變量擴充到一個路徑 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~nI %%~ni --僅將變量擴充到一個文件名 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~xI %%~xi --僅將變量擴充到一個文件擴展名 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~sI %%~si --擴充的路徑只含有短名 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~aI %%~ai --將變量擴充到文件的文件屬性 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~tI %%~ti --將變量擴充到文件的日期/時間 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~zI %%~zi --將變量擴充到文件的大小 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~$PATH:I %%~$PATH:i --查找列在路徑環境變量的目錄,並將變量擴充到找到的第一個完全合格的名稱 echo ---以下顯示組合修飾符來得到多重結果---: for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~dpI %%~dpi --僅將變量擴充到一個驅動器號和路徑 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~nxI %%~nxi --僅將變量擴充到一個文件名和擴展名 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~fsI %%~fsI --僅將變量擴充到一個帶有短名的完整路徑名 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~dp$PATH:I %%~dp$PATH:i --查找列在路徑環境變量的目錄,並將變量擴充到找到的第一個驅動器號和路徑 for /f "delims==" %%i in ('dir C:\WINDOWS\system32\notepad.exe /b') do echo 擴展變量到~ftzaI %%~ftzai --將變量擴充到類似輸出線路的DIR Pause
TTT說明: 1,以上命令中,%%~fsI無法顯示,估計是系統錯誤,因為%%~fI是擴充到一個完全合格的路徑名,%%~sI只含有短文件名,本身是相互矛盾的,所以出錯。不知是系統的錯誤還是在考我們~~ 2,以上命令如果保存在別的盤中,無法顯示正確的驅動器和路徑。 3,如果想要%%~dp$PATH:i正常顯示,要保證環境變量path中確實有這個路徑:C:\WINDOWS\system32。 下面依次說明一下: +++ 一、 ~I - 刪除任何引號("),擴展 %I --- 這個變量的作用就如他的說明,刪除引號! 刪除引號規則如下(BAT兄補充!): 1、若字符串首尾同時存在引號,則刪除首尾的引號; 2、若字符串尾不存在引號,則刪除字符串首的引號; 3、如果字符串中間存在引號,或者只在尾部存在引號,則不刪除。 龍卷風補充:無頭不刪,有頭連尾刪。
我們來看這個例子,首先建立臨時文件temp.txt,內容如下 "1111 "2222" 3333" "4444"44 "55"55"55 也可建立個BAT文件代碼如下:
@echo off echo ^"1111>temp.txt echo "2222">>temp.txt echo 3333^">>temp.txt echo "4444"44>>temp.txt echo ^"55"55"55>>temp.txt rem 上面建立臨時文件,注意不成對的引號要加轉義字符^,重定向符號前不要留空格 FOR /F "delims=" %%i IN (temp.txt) DO echo %%~i pause del temp.txt
執行后,我們看CMD的回顯如下: 1111 #字符串前的引號被刪除了 2222 #字符串首尾的引號都被刪除了 3333" #字符串前無引號,后面的引號保留 4444"44 #字符串前面的引號刪除了,而中間的引號保留 55"55"55 #字符串前面的引號刪除了,而中間的引號保留 請按任意鍵繼續. . .
結果和之前temp.txt中的內容對比一下,我們會發現第1、2、5行的引號都消失了,這就是刪除引號~i的作用了! +++ 二、 %~fI - 將 %I 擴展到一個完全合格的路徑名 示例: 把代碼保存放在隨便哪個地方,我這里就放桌面吧. FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~fi pause
執行后顯示內容如下 C:\Documents and Settings\Administrator\桌面\test.bat C:\Documents and Settings\Administrator\桌面\test.vbs 當我把代碼中的 %%~fi直接改成%%i FOR /F "delims==" %%i IN ('dir /b') DO @echo %%i pause 執行后就會顯示以下內容: test.bat test.vbs 通過對比,我們很容易就看出沒有路徑了,這就是"將 %I 擴展到一個完全合格的路徑名"的作用,也就是如果%i變量的內容是一個文件名的話,他就會把這個文件所在的絕對路徑打印出來,而不只單單打印一個文件名,自己動手動實驗下就知道了! +++ 三、 %~dI - 僅將 %I 擴展到一個驅動器號 看例子: 代碼如下,我還是放到桌面執行! FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~di pause 執行后我CMD里顯示如下 C: C: 我桌面就兩個文件test.bat,test.vbs,%%~di作用是,如果變量%%i的內容是一個文件或者目錄名,他就會把他這文件或者目錄所在的盤符號打印出來!
+++ 四、 %~pI - 僅將 %I 擴展到一個路徑 這個用法和上面一樣,他只打印路徑不打印文件名字 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~pi pause 我就不打結果了,大家自己復制代碼看結果吧,下面幾個都是這么個用法,代碼給出來,大家自己看結果吧!
+++ 五、 %~nI - 僅將 %I 擴展到一個文件名 只打印文件名字 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~ni pause
+++ 六、 %~xI - 僅將 %I 擴展到一個文件擴展名 只打印文件的擴展名 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~xi pause
+++ 七、 %~sI - 擴展的路徑只含有短名 打印絕對短文件名 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~si pause
+++ 八、 %~aI - 將 %I 擴展到文件的文件屬性 打印文件的屬性 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~ai pause
+++ 九、 %~tI - 將 %I 擴展到文件的日期/時間 打印文件建立的日期 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~ti pause
+++ 十、 %~zI - 將 %I 擴展到文件的大小 打印文件的大小 FOR /F "delims==" %%i IN ('dir /b') DO @echo %%~zi pause 龍卷風補充:上面例子中的"delims=="可以改為"delims=",即不要分隔符
+++ 十一、 %~$PATH:I - 查找列在路徑環境變量的目錄,並將 %I 擴展到找到的第一個完全合格的名稱。如果環境變量名未被定義,或者沒有找到文件,此組合鍵會擴展到空字符串 這是最后一個,和上面那些都不一樣,我單獨說說! 然后在把這些代碼保存為批處理,放在桌面。 @echo off FOR /F "delims=" %%i IN (“notepad.exe”) DO echo %%~$PATH:i pause 龍卷風補充:上面代碼顯示結果為C:\WINDOWS\system32\notepad.exe 他的意思就在PATH變量里指定的路徑里搜索notepad.exe文件,如果有notepad.exe則會把他所在絕對路徑打印出來,沒有就打印一個錯誤! (TTT說明,保存到桌面上,運行顯示結果為:系統找不到文件 “notepad.exe”。查看環境變量path中確實有這個路徑,不明原因!后來發現了,原來是中文引號的原因。 上面的命令應該寫成: FOR /F "delims=" %%i IN ("notepad.exe") DO echo %%~$PATH:i ) 最后發一個用批處理做一五子棋游戲:@echo off&setlocal enabledelayedexpansionmode con: lines=43 cols=110set li39= A B C D E F G H I J K L M N O P Q R Sset li0= ┌─────────────────────────────────────┐set li1=A│┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐│Aset var=1for %%a in (!li39:~5^,-1!) do (set/a var+=2&set li!var!=%%a│├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤│%%a)for /l %%a in (2,2,36) do (set li%%a= ││ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ││)set li37=S│└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘│Sset li38= └─────────────────────────────────────┘set str=a b c d e f g h i j k l m n o p q r sfor %%a in (%str%) do (set/a .+=1,%%a=.&set z!.!=%%a)set li5=!li5! 五 棋 子 人 機 對 戰set li7=!li7! 批 處 理set li10=!li10! 電 腦 水 平 中 等set li31=!li31! 由 netbenton 編寫完成set li33=!li33! 棋盤設計參照了 batmantitle 批處理五子棋
set str=###################set .=0for /l %%a in (1,1,19) do ( set he%%a=!str!&set sh%%a=!str! for /l %%b in (1,1,19) do set [%%a.%%b=0)set .=33for /l %%a in (5,1,19) do ( set pi%%a=!str:~,%%a!&set ni%%a=!str:~,%%a! set pi!.!=!str:~,%%a!&set ni!.!=!str:~,%%a! set/a .-=1)
set ●=○&set ○=●set zhi=●set say=say::設置電腦IQset idea=@@@@#.1 #@@@@.5 @#@@@.4 @@@#@.2 @@#@@.3 vs0#.1 #.5.3 $#$#$.2 vs1#@@@##.2 ##@@@#.5 #@@#@#.3 #@#@@#.4 vs2 #@##@@#.4-5 #@@##@#.4-3 #@#@@.3-5 @#@@#.4-1 #@@@##.2-W-1##@@@#.5-W-6 vs3set idea=!idea! ##@@@.4-W-5 @@@##.2-W-1 @##@@#.4-5 #@##@@.3-4 #@#@#@.4-2 @#@#@#.3-5 vs4 ##.4-W-1-6 ##$##.2-W-1-6 vs5 ##@@##.2-5-W-6-1 #@#@#.3-w-1-5 ##$##.W-2-1.W-3-4 $##$.W-2-5 ####.W-2-W-1-5 #$#$#.W-3-W-1-5 #$##$#.W-3-4set idea=!idea! vs7 #$$$#.1-5 @@###.4-3 ###@@.3-4 ###@###.3-5-W-2-6-W-1-7 vs8 ###$###.3-5 vs9 @####.4 ####@.2 #$###.3 ###$#.3set idea=!idea! ###@#.3 #@###.3 $####.3 ####$.3.3 $#$##.2 ##$#$.4 #$##$.3 $##$#.3 $###$.3 vs10set iqam=1000000000:restart(setlocal enabledelayedexpansionfor /l %%a in (0,1,39) do (echo !li%%a!)set li39=!li39! reboot重新開始,exit退出。set li37=!li37! back 悔棋set /p var=選擇誰先下[ W,玩家 D,電腦 Q,退出 ]:if /i "!var!" equ "Q" goto :quitif /i "!var!" equ "D" (set onez=○&set towz=●&set hou=☆) else (set onez=●&set towz=○&set hou=★)set a!onez!=電腦&set a!towz!=玩家)(set ttr=!idea=%onez%!&set ttr=!ttr=%towz%!set idea=for %%a in (!ttr!) do ( for /f "tokens=1,2 delims=." %%b in ("%%a") do (set %%b=%%c&set idea=!idea! %%b))set ttr=set li27=!li27! !onez! !a%onez%!set li25=!li25! !towz! !a%towz%!set/a pos=10,poh=10&goto :getok):loop(if %zhi% equ %onez% goto :menset .=setlocal enabledelayedexpansionfor %%a in (!idea!) do ( set str=%%a if "!str:~,2!" neq "vs" ( for %%b in (he sh) do ( set all=!%%b1!!%%b2!!%%b3!!%%b4!!%%b5!!%%b6!!%%b7!!%%b8!!%%b9!!%%b10!!%%b11!!%%b12!!%%b13!!%%b14!!%%b15!!%%b16!!%%b17!!%%b18!!%%b19! if "!all:%%a=!" neq "!all!" ( for /l %%c in (1,1,19) do ( if "!%%b%%c:%%a=!" neq "!%%b%%c!" set/a .+=1&set put!.!=%%b %%c.%%a.!iqam! ) ) ) for %%b in (pi ni) do ( set all=!%%b5!!%%b6!!%%b7!!%%b8!!%%b9!!%%b10!!%%b11!!%%b12!!%%b13!!%%b14!!%%b15!!%%b16!!%%b17!!%%b18!!%%b19!!%%b20!!%%b21!!%%b22!!%%b23!!%%b24!!%%b25!!%%b26!!%%b27!!%%b28!!%%b29!!%%b30!!%%b31!!%%b32!!%%b33! if "!all:%%a=!" neq "!all!" ( for /l %%c in (5,1,33) do ( if "!%%b%%c:%%a=!" neq "!%%b%%c!" set/a .+=1&set put!.!=%%b %%c.%%a.!iqam! ) ) ) ) else ( set/a "iqam=(iqam+1)/8" if %%a equ vs8 if defined . goto :get if %%a equ vs9 if defined . goto :get )))if defined . (goto :get)echo. 已經和棋了 pauseendlocal&goto :restart:men(set/a .=lips-1&for /f "tokens=1-3" %%b in ("li!liph! !lips! !.!") do (set %%b=!%%b:~0,%%d!%hou%!%%b:~%%c!)set li38=!li38![%悔:~,24%]clsfor /l %%a in (0,1,39) do (echo !li%%a!)for /f "tokens=1-3" %%b in ("li!liph! !lips! !.!") do (set %%b=!%%b:~0,%%d!%zhi%!%%b:~%%c!)set li38=%li38%set /p user=!say:say=%error%! [列前,行后]: if "!user!" equ "reboot" endlocal&goto :restartif "!user!" equ "exit" goto :quitif "!user!" equ "back" call :悔&goto :menset/a pos=!user:~0,1!,poh=!user:~1,2!,var=pos-1 2>nulif not defined [!poh!.!pos! set error=輸入點不存在 &goto :men)if "!he%poh%:~%var%,1!" neq "#" set error=該點已經有子 &goto mengoto :getok:getset `=::取最佳的走法for /l %%z in (!.!,-1,1) do (for /f "tokens=1,2,3 delims=." %%1 in ("!put%%z!") do (for /f "tokens=1-4" %%a in ("%%1 %%2") do ( set iqm=%%3 set vara=!%%a%%b:*%%c=!srqponmlkjihgfedcba0 for %%4 in (!%%2:-^=;!) do ( if "%%4" equ "W" (set/a iqm=iqm/5*3) else ( set/a var=!vara:~19,1!+%%4 if "%%a" equ "he" (set/a poh=%%b,pos=20-var) if "%%a" equ "sh" (set/a poh=20-var,pos=%%b) if %%b lss 19 (set/a var=%%b-var+1) else (set/a var=38-%%b-var+1) if "%%a" equ "pi" (if %%b lss 19 (set/a pos=var,poh=%%b-var+1) else (set/a poh=20-var,pos=%%b-19+var)) if "%%a" equ "ni" (if %%b lss 19 (set/a pos=var,poh=19-%%b+var) else (set/a poh=var,pos=%%b-19+var)) if not defined R!pos!R!poh!R set /a `+=1&set ram!`!=R!pos!R!poh!R set/a R!pos!R!poh!R+=iqm ) ))))set rmk=0for /l %%a in (1,1,!`!) do ( for %%b in (!ram%%a!) do ( for %%c in (!%%b!) do ( if %%c gtr !rmk! set/a rmk=%%c,.=0 if %%c equ !rmk! set rmz!.!=%%b&set/a .+=1 )) )set/a .=!random!%%.for /f "tokens=1,2 delims=R" %%a in ("!rmz%.%!") do (set/a pos=%%a,poh=%%b)rem start set r^&echo !.!^&pause^&exit
endlocal&set/a pos=%pos%,poh=%poh%set say=say !z%pos%!!z%poh%!(%poh%)&set error=電腦最后下在::getokset zhi=!%zhi%!&set win=!zhi!!zhi!!zhi!!zhi!!zhi!(set/a piph=poh+pos-1,lips=pos*2+1,niph=19+pos-poh,liph=poh*2-1if !piph! lss 19 (set/a pips=pos) else (set/a pips=20-poh)if !niph! lss 19 (set/a nips=pos) else (set/a nips=poh)for %%a in ("li!liph! !lips!" "he!poh! !pos!" "sh!pos! !poh!" "pi!piph! !pips!" "ni!niph! !nips!") do ( for /f "tokens=1,2" %%b in (%%a) do ( set/a .=%%c-1 for %%d in (!.!) do (set %%b=!%%b:~0,%%d!%zhi%!%%b:~%%c!) if "!%%b:%win%=!" neq "!%%b!" set win=y )))(set/a asc%zhi%+=1set 悔= !z%pos%!!z%poh%!!悔!if !win! neq y goto :loop)for /l %%a in (0,1,39) do (echo !li%%a!)set/p= !a%zhi%! %zhi%子 第!asc%zhi%!手 !z%pos%!!z%poh%!(%poh%) 勝出 <nulpauseendlocal&goto :restart:悔if not defined 悔 goto :eofif "!悔:~6,1!" equ "" goto :eoffor %%a in (!悔:~^,6!) do (set str=%%aset/a poh=!str:~-1!,pos=!str:~,1!set/a piph=poh+pos-1,niph=19+pos-poh,liph=poh*2-1,lips=pos*2+1if !piph! lss 19 (set/a pips=pos) else (set/a pips=20-poh)if !niph! lss 19 (set/a nips=pos) else (set/a nips=poh)for %%a in ( "he!poh! !pos!" "sh!pos! !poh!" "pi!piph! !pips!" "ni!niph! !nips!") do ( for /f "tokens=1,2" %%b in (%%a) do ( set/a .=%%c-1 for %%d in (!.!) do (set %%b=!%%b:~0,%%d!#!%%b:~%%c!) ))for /f "tokens=1,2" %%b in ("li!liph! !lips!") do ( set/a .=%%c-1 for %%d in (!.!) do (set %%b=!%%b:~0,%%d!┼!%%b:~%%c!)))set/a asc%zhi%-=1set 悔=!悔:~6!set error=你悔棋,耍賴皮!if not defined 悔 goto :eofset/a poh=!悔:~2,1!,pos=!悔:~1,1!,liph=poh*2-1,lips=pos*2+1set say=say !z%pos%!!z%poh%!(%poh%)goto :eof:quittaskkill /fi "WINDOWTITLE eq 批處理五子棋*" /im cmd.exe
---恢復內容結束---