我的GitHub | 我的博客 | 我的微信 | 我的郵箱 |
---|---|---|---|
baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
目錄
FOR 命令使用總結
for /? > for_help.txt
- 在
批處理程序
中使用 FOR 命令時,指定變量請使用%%variable
而不要用%variable
。 - 變量名稱是
區分大小寫
的,所以%i
不同於%I
。
FOR
FOR %variable IN (set) DO command [command-parameters]
對一個 set 中的每一個元素(文件)執行某個特定命令。
%variable
指定一個單一字母
可替換的參數,可以使用但盡量不要使用數字(set)
指定一個集合,每個元素(文件)之間,可以用空格、跳格、逗號、分號或等號
分隔;可以使用通配符匹配文件command
指定對每個元素(文件)執行的命令command-parameters
為特定命令指定參數或命令行開關
for %%i in (1 2 3 4 5) do @echo %%i
for %%i in (c d e f g h i j k l m n o p q r s t u v w x y z) do if exist %%i: echo 存在分區%%i:
set /a num=0
for %%j in (%*) do set /a num+=1
echo 批處理文件調用的參數個數:%num%
for %%i in (*) do echo %%i %【當前目錄下的所有文件,不包括目錄】%
for %%i in (*.txt) do echo "%%i" %【當前目錄下的所有.txt文件】%
for %%i in (??.txt) do echo "%%i" %【當前目錄下的所有只用兩個字符作為文件名的.txt文件】%
列出當前目錄下各種文件的方法,最簡單的還是用
dir
命令
FOR /D
FOR /D %variable IN (set) DO command [command-parameters]
D是指directory
,即為了處理文件夾。
有通配符
- 當 set 中包含有通配符
?
或*
時,它會匹配文件夾
,而不會匹配文件
- 不能匹配帶隱藏屬性的文件夾
- 它僅能匹配當前目錄下的
第一級文件夾
,或是指定目錄位置上的一級文件夾,而不能匹配更深路徑下的子文件夾,即不能遞歸
。
for /d %%i in (*) do echo %%i %【當前目錄下的所有子目錄,不包括文件】%
for %%i in (*) do echo %%i %【當前目錄下的所有文件,不包括目錄】%
無通配符
當 set 中不包含任何的通配符時,它的作用和上面不帶命令擴展時的語句無任何區別
。
- 不會排除掉帶隱藏屬性的文件夾
- 不會排除掉文件
- 總之就是和不帶
/d
時無任何區別
for /d %%i in (test test.txt) do echo %%i
for %%i in (test test.txt) do echo %%i
/D /R 同時使用
for /d /r
其實是對/d
參數的擴展,/d
參數本身只能處理第一層文件夾,但是加上/r
參數后就可以處理所有的子文件夾。
- 在 for 有限的 4 個參數中,只有
/d
/r
可以一起使用(不分前后順序) - 依然不能處理隱藏文件夾
For /d /r %%i in (*) do echo %%i
:: 顯示當前目錄下所有的文件夾(包括子文件夾),等價於【dir /ad /s /b】
FOR /R
FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]
R 是指Recursive
,即遞歸
,換一個通俗一點的叫遍歷文件夾
。
- 列舉 set 及其之下的所有以
[drive:]path
為根的子目錄,對這些文件夾都執行 command 語句 - 如果在
/R
后沒有指定目錄,則默認使用當前目錄
- 由於
/R
語句是邊列舉路徑邊進行處理,所以在處理大量路徑的時候,過程前期不會感到有停頓
set 是一個點號
如果 set 僅為一個點(.
)字符,則枚舉該目錄樹
- 不能列舉帶隱藏屬性的目錄
- 列舉出來的路徑最后都帶有
斜杠和點號
,例如D:\_test\.
D:\_test\bqt\.
for /r D:\_test\bqt %%i in (.) do echo %%i
for /r \_test\bqt %%j in (.) do echo %%j
for /r %%k in (.) do echo %%k
set 帶通配符
列舉[[drive:]path]
及其所有子目錄下滿足指定規則的文件
(不包括文件夾)。
for /r d:\_test %%i in (*.txt *bat*) do echo %%i
:: 列舉指定目錄下所有.txt結尾的文件,或所有文件名中包括bat的文件,不包括文件夾
set 不帶點號或通配符
列舉[[drive:]path]
及其所有的子目錄
(不包括文件),都分別添加 set 的元素之后再顯示出來
。
for /r D:\_test %%i in (包 青 天) do echo %%i
FOR /L
FOR /L %variable IN (start,step,end) DO command [command-parameters]
L是指loop
,即循環的意思。該集表示以增量形式從開始到結束的一個數字序列
- 所有的for語句,都可以看成是一種循環,只是在
/l
中,特指按照指定次數進行循環罷了 - start指起始值,step指步間距,end指終止值
- start、step和end都只能取整數,正負皆可
- 以上會遍歷出所有滿足以下條件的整數值:
k = start + n*step
,並且k <= end
,其中n=0,1,2,3...
必須保證能取到一個有效的數組序列
- 步間距step的值不能為0
- 當步間距step的值為正整數時,終止值end不能小於初始值start
- 當步間距step的值為負整數時,終止值end不能大於初始值start
for /L %%k in (0,1,3) do echo %%k %【0 1 2 3】%
for /L %%k in (0,-1,-3) do echo %%k %【0 -1 -2 -3】%
一般而言,for /l
語句可以換成goto
循環,但是,goto
循環並不一定能被for /l
語句替換掉。
- 當循環次數確定的時候,首選
for /l
語句 - 當循環次數不確定的時候,只能使用
goto
語句,因為這個時候需要用if
之類的條件語句來判斷何時結束goto
跳轉
FOR /F
FOR /F ["options"] %variable IN (file-set/"string"/'command') DO command [command-parameters]
基本用法
所有的對象,無論是文件、窗體、還是控件,在所有的非機器語言
看來,無外乎都是的文本信息,可以說,編程的很大一部分工作,都是在想方設法絞盡腦汁如何提取這些文本信息。
而for /f
就是被設計成專門用於解析文本的。
- 無論for語句做何種變化,它的執行過程仍然遵循基本的流程:依次處理每個元素,直到所有的元素都被處理為止
- 在
for /f
語句中,這里的元素是指文件中的每一行
,這是一條極為重要的規則
for /f %%i in (test.txt) do echo %%i %逐行打印指定文件的內容%
for /f %%i in (test.txt) do echo %%i&pause
delims
- 以指定的
符號列表
(符號只能是一個
字符/字母/數字/漢字)作為被處理的字符串的分隔符集
,切分字符串 - 默認只提取
第一節
的字符串作為最終結果 - 如果沒有指定
delims=符號列表
這個開關,默認以空格鍵或跳格鍵
作為分隔符號 - 可以一次性指定多個分隔符號
for /f "delims= " %%i in (test.txt) do echo %%i
for /f "delims=12青天ab" %%i in (test.txt) do echo %%i %這里面的分割符有6個%
tokens
tokens=
后面一般跟的一個或多個是數字,每個數字之間用逗號
分隔- 數字的含義是:提取由
delims=
這一開關划分的第n
節字符串,划分的節是從1
開始算的 - 如果
tokens=
后面指定了多個數字,那么形式變量必須按照字母順序定義,例如%%i
%%j
%%k
- 如果要提取的內容是
連續的
多節的話,那么連續的數字可以使用start-end
的形式替換 - 如果
tokens=
最后一個字符是星號,則后面的內容整體
被星號所表示的一個變量接收
for /f "delims=, tokens=2" %%i in (test.txt) do echo %%i
for /f "delims=, tokens=1,3" %%i in (test.txt) do echo %%i---%%j
for /f "delims=, tokens=1,2-4" %%i in (test.txt) do echo %%i---%%j---%%k---%%l
for /f "delims=, tokens=1-2,4,5-8" %%i in (test.txt) do echo %%i
for /f "delims=, tokens=1,*" %%i in (test.txt) do echo %%i---%%j
for /f "delims=, tokens=1,2-3,*" %%i in (test.txt) do echo %%i---%%j---%%k---%%l
skip
skip=n
,其中,n是一個正整數,表示在文件開始時要跳過的行數
for /f "skip=2" %%i in (test.txt) do echo %%i
eol
eol=
表示忽略以指定字符打頭的行- 在指定字符的時候,
只能指定1個
,也可以不指定(即強制指定字符為空) for /f
語句是默認忽略以;
打頭的行內容的(這種默認設置在delims=;
時無效),很多時候,我們可以充分利用這個特點,比如,在設計即將用for
讀取的配置文件的時候,可以在注釋文字的行首加上分號
for /f "eol=," %%i in (test.txt) do echo %%i
命令的 3 種形式
for /f %%i in (test.txt) do echo %%i %第2種形式:文件名%
for /f "delims=" %%i in ('dir .') do echo %%i %第2種形式:單引號+命令語句%
for /f "tokens=1,*" %%i in ("hello 包 青天 ") do echo %%i--%%j %第3種形式:雙引號+字符串%
usebackq 的使用
如果文件名中含有空格
等特殊字符,例如test 1.txt
,該怎么辦?
for /f %%i in (test 1.txt) do echo %%i %錯誤:找不到文件%
for /f %%i in ("test 1.txt") do echo %%i %錯誤:這是第3種形式,文件名被當做字符串處理了%
usebackq
是一個增強型參數,當使用了這個參數之后,原來的for
語句中第一個括號內的寫法要做如下變動:
- 如果第一個括號里的對象是
文件名
的話,要用雙引號"
括起來 - 如果第一個括號里的對象是一條
命令語句
的話,原來的單引號'
要改為后引號 - 如果第一個括號里的對象是
字符串
的話,原來的雙引號"
要改為單引號'
for /f "usebackq" %%i in ("test 1.txt") do echo %%i
FOR /F %%i IN ('set') DO @echo %%i %枚舉當前環境中的環境變量%
FOR /F "usebackq" %%i IN (`set`) DO @echo %%i
usebackq
除了在處理帶空格的文件名
時會用到外,根本就沒有其它的出場機會和存在價值。
遲環境變量的理解
變量延遲是批處理中一個十分重要的機制,它因預處理機制而生,用於復合語句,特別是大量使用於強大的for語句中,所以需要熟練地使用這一機制。
setlocal enabledelayedexpansion
語句的解釋:
set
設置,local
本地(局部),enable
能夠,delayed
延遲,expansion
擴展- 合起來就是:將變量設置為
局部變量
,並延遲環境變量的擴展行為
批處理的執行過程是怎樣的?
自上而下,逐條執行
逐條
並不等同於逐行
,這個條
,是一條完整的語句
的意思,並不是指一行代碼
什么樣的語句才算一條完整的語句
?
- 在
非復合語句
中,如果該語句占據了一行
的位置,則該行代碼為一條完整的語句 - 在
復合語句
中,整個復合語句是一條完整的語句
,而無論這個復合語句占用了多少行的位置 - 常見的復合語句有:
for
語句、if……else
語句、用符號&、||、&&、|
連接的語句,以及用括號
括起來的語句塊
在代碼逐條執行的過程中,批處理解釋器
會對每條語句
做一些預處理工作
,這就是批處理中大名鼎鼎的預處理機制
!
預處理機制的基本過程:
- 首先,把
一條完整的語句
讀入內存中,不管這條語句有多少行,它們都會被一起讀入 - 然后,識別出哪些部分是命令關鍵字,哪些是開關、哪些是參數,哪些是變量引用……
- 如果代碼語法有誤,則給出錯誤提示或退出批處理環境
- 如果順利通過,接下來,就把該條語句中所有被
引用的變量
及變量兩邊的百分號對
,用這條語句被讀入內存之前
就已經賦予該變量的具體值
來替換…… - 當所有的預處理工作完成之后,批處理才會執行每條完整語句內部每個命令的原有功能
所以,如果命令語句中含有
變量引用
,並且某個變量的值在命令的執行過程中被改變了
,即使該條語句內部
的其他地方也用到了這個變量,也不會用最新的值去替換它們,因為某條語句在被預處理的時候,所有的變量引用都已經被替換成字符串常量了
。
解決的辦法是:使用變量延遲擴展語句,即讓變量的擴展行為延遲一下
,延遲之后,就可以讓復合語句內部的變量實時感知到變量值的變化
,從而獲取我們想要的值
變量擴展
是怎么一回事?
- 在許多可見的官方文檔中,均將使用一對百分號閉合環境變量以完成對其值的替換行為,稱之為
擴展(expansion)
- 這其實是一個
第一方
的概念,是從命令解釋器
的角度進行稱謂的,而從我們使用者
的角度來看,則可以將它看作是引用(Reference)
- 說得直白一點,所謂的變量擴展,實際上就是很簡單的這么一件事情:
用具體的值去替換被引用的變量及緊貼在它左右的那對百分號
哪些場合需要使用變量延遲語句?
在復合語句內部,如果某個變量的值發生了改變,並且
改變后的值需要在復合語句內部的其他地方被用到
,那么就需要使用變量延遲語句。
延遲變量的擴展行為的兩種方式:
- 在適當位置使用
setlocal enabledelayedexpansion
語句,然后把原本使用百分號對
閉合的變量引用改為使用感嘆號對
來閉合;這種方式非常常見 - 在適當的位置使用
call
語句,即:在原來命令的前部加上call
命令,並把變量引用的單層百分號對
改為雙層百分號對
;這種方式用得較少
@echo off & setlocal enabledelayedexpansion
set num=0 && echo !num!
@echo off
set num=0 && call echo %%num%%
2019-12-25