BAT 批處理 for循環 遲環境變量 [MD]


博文地址

我的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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM