- 帖子
- 83
- 主題
- 73
- 精華
- 0
- 積分
- 164
- 點名
- 0
- 作業系統
- xp
- 軟體版本
- Office 2003
- 閱讀權限
- 20
- 性別
- 男
- 註冊時間
- 2013-8-12
- 最後登錄
- 2015-12-13
|
3#
倒序看帖
發表於 2013-8-14 19:02
| 只看該作者
[教學] BAT批次指令: For的功能範例詳解- 二
由於排版問題:部分語法中的FOR指令字元後面的間隔不見~在語法中要注意的~修正後再貼一次~
BAT批次指令: For 的功能範例詳解- 二
-----------------------------------------------------------------------------------------------
‧ 基本套用
‧ 簡單說,For 是個循環,可以用你指定的循環範圍產生一系列指令。
‧ 最簡單的例子,就是人工指定循環範圍,然後對每個值執行指定的指令。
‧ 例如,想快速報告每個硬碟分區的剩餘空間:
For %a in (c: d: e: f do @dir %a\ | find "bytes free"
‧ 將輸出:
‧ 8 Dir(s) 1,361,334,272 bytes free
‧ 15 Dir(s) 8,505,581,568 bytes free
‧ 12 Dir(s) 12,975,149,056 bytes free
‧ 7 Dir(s) 11,658,854,400 bytes free
‧ 用它可以使一些不支持萬用字元的指令對一系列文件進行操作。
‧ 遇到類似情況就可以用For :
For %a in (*.txt) do type %a
‧ 這些還不是For 最強大的功能。
‧ 它最強大的功能,表現在以下這些進階套用:
‧ 1. 可以用 /r 參數遍歷整個目錄樹
‧ 2. 可以用 /f 參數將文本文件內容作為循環範圍
‧ 3. 可以用 /f 參數將某一指令執行結果作為循環範圍
‧ 4. 可以用 %~ 操作符將檔案名分離成檔案名、副檔名、磁碟代號等獨立部分
‧ 現分別舉例說明如下:
1. 用 /r 遍歷目錄樹:
‧ 當用 *.* 或 *.txt 等檔案名萬用字元作為 For /r 的循環範圍時,可以對當前目錄下所有文件(包括子目錄裡面的文件)進行操作。
‧ 舉個例子,你想在當前目錄的所有txt文件(包括子目錄)內容中尋找"bluebear"字樣,但由於find本身不能遍歷子目錄,
‧ 所以我們用For :
For /r . %a in (*.txt) do @find "bluebear" %afind
‧ 前面的 @ 只是讓輸出結果不包括 find 指令本身。
‧ 這是DOS很早就有的功能。和For 無關。
‧ 當用 . 作為循環範圍時,For 只將子目錄的結構(目錄名)作為循環範圍,而不包括裡面的文件。
‧ 有點像 TREE 指令,不過側重點不同。
‧ TREE 的重點是用很漂亮易讀的格式輸出,而For 的輸出適合一些自動工作,例如,
‧ 我們都知道用CVS管理的項目中,每個子目錄下都會有一個CVS目錄,有時在軟體發行時我們想把這些CVS目錄全部去掉:
For /r . %a in (.) do @if exist %a\CVS rd /s /q %a\CVS
‧ 先用 if exist 判斷一下,是因為 For 只是機械的對每個目錄進行列舉,如果有些目錄下面沒有CVS也會被執行到。
‧ 用 if exist 判斷一下比較安全。
‧ 這種移除指令威力太大,請小心使用。
‧ 最好是在真正執行以上的移除指令前,將 rd /s /q 換成 @echo 先列出要刪出的目錄,驗證無誤後再換回rd /s /q:
For /r . %a in (.) do @if exist %a\CVS @echo %a\CVS
‧ 可能目錄中會多出一層 ".",比如 c:\proj\release\.\CVS ,但不會影響指令的執行效果。
2. 將某一文件內容或指令執行結果作為循環範圍:
‧ 假如你有一個文件 todel.txt,裡面是所有要移除的文件列表,現在你想將裡面列出的每個文件都刪掉。
‧ 假設這個文件是每個檔案名占一行,如下列:
‧ c:\temp\a1.txt
‧ c:\temp\a2.txt
‧ c:\temp\subdir\b3.txt
‧ c:\temp\subdir\b4.txt
‧ 那麼可以用For 來完成:
For /f %a in (todel.txt) do del %a
‧ 這個指令還可以更強大。
‧ 再如你的 todel.txt 並不是像上面排列整齊乾淨,而是由DIR直接產生,含有有部分沒用的訊息,如下列:
‧ Volume in drive D is DATA
‧ Volume Serial Number is C47C-9908
‧
‧ Directory of D:\tmp
‧ 09/26/2012 12:50 PM 18,426 alg0925.txt
‧ 12/02/2012 04:29 AM 795 bsample.txt
‧ 04/11/2013 04:18 AM 2,043 invitation.txt
‧ 4 File(s) 25,651 bytes
‧ 0 Dir(s) 4,060,700,672 bytes freeFor
‧
‧ 仍然可以解出其中的檔案名並進行操作:
For /f "skip=5 tokens=5" %a in (todel.txt) do @if exist %a DEL %a
‧ 當然,上面這個指令是在進行移除,如果你只是想看看哪些文件將被操作,把DEL換成echo:
For /f "skip=5 tokens=5" %a in (todel.txt) do @if exist %a echo %a
‧ 你將看到:
‧ alg0925.txt
‧ bsample.txt
‧ invitation.txtskip=5
‧ 表示跳過前5行(就是DIR輸出的頭部訊息),tokens=5表示將每行的第5列作為循環值放入%a,正好是檔案名。
‧ 在這裡加了一個文件存在判斷,是因為最後一行的"free"剛好也是第5列,目前還想不出好的辦法來濾掉最後兩行,所以檢查一下可保萬無一失。
3. 可以用 /f 參數將某一指令執行結果作為循環範圍
‧ 非常有用的功能。
‧ 比如,我們想知道目前的環境變數有哪些名字(我們只要名字,不要值)。
‧ 可是SET指令的輸出是「名字=值」的格式,現在可以用For 來只取得名字部分:
For /F "delims==" %i IN ('set') DO @echo %i
‧ 將看到:
‧ ALLUSERSPROFILE
‧ APPDATA
‧ CLASSPATH
‧ CommonProgramFiles
‧ COMPUTERNAME
‧ ComSpec
‧ dircmd
‧ HOMEDRIVE
‧ .....這裡是將set指令執行的結果拿來作為循環範圍。
‧ delims==表示用=作為分隔符,由於For /F預設是用每行第一個TOKEN,所以可以分離出變數名。
‧ 如果是想僅列出值:
For /F "delims== tokens=2" %i IN ('set') DO @echo %itokens=2
‧ 和前例相同,表示將第二列(由=作為分隔符)作為循環值。
‧ 再來個更有用的例子:
‧ 我們知道 date /t (/t表示不要詢問用戶輸入)的輸出是像這樣的:
‧ Sat 07/13/2013
‧ 現在我想分離出日期部分,也就是13:
For /f "tokens=3 delims=/ " %a in ('date /t') do @echo %a
‧ 實際上把 tokens後面換成1,2,3或4,你將分別得到Sat, 07, 13和2002。
‧ 注意delims=/後面還有個空格,表示/和空格都是分隔符。
‧ 由於這個空格delims必須是/f選項的最後一項。
‧ 再靈活一點,像本文開頭提到的,將日期用2013-07-13的格式輸出:
For /f "tokens=2,3,4 delims=/ " %a in ('date /t') do @echo %c-%a-%b
‧ 當tokens後跟多個值時,將分別映射到%a, %b, %c等。
‧ 實際上跟你指定的變數有關,如果你指定的是 %i, 它們就會用%i, %j, %k等。
‧ 靈活套用這一點,幾乎沒有做不了的事。
4. 可以用 %~ 操作符將檔案名分離成檔案名、副檔名、磁碟代號等獨立部分
‧ 這個比較簡單,就是說將循環變數的值自動分離成只要檔案名,只要副檔名,或只要磁碟代號等等。
‧ 例:要將 c:\mp3下所有mp3的歌名列出,如果用一般的 dir /b/s 或 For /r ,
‧ 將會是這樣:
‧ g:\mp3\Archived\13-08-01-A\資料夾1\01 夕陽.mp3
‧ g:\mp3\Archived\13-08-01-A\資料夾1\02 烈日.mp3
‧ .................................................
‧ g:\mp3\Archived\13-08-01-A\資料夾2\童話.mp3
‧ g:\mp3\Archived\13-08-01-A\資料夾2\神話.mp3
‧ g:\mp3\Archived\13-08-01-A\資料夾2\四季.mp3
‧ ......如果只要歌名(不要路徑和".mp3"):
‧ ......
‧ 那麼可以用For 指令:
For /r g:\mp3 %a in (*.mp3) do @echo %~na
‧ 凡是 %~ 開頭的操作符,都是檔案名的分離操作。
‧ 如果想將電腦上有一些虛擬光碟,來源碟的格式是wav的,想用lame壓一下。
‧ 如果每個虛擬盤結構為:wave資料夾下有子8個左右子資料夾,每個子資料夾內有一些wave文件,
‧ 如將這些文件壓到指定的位置,轉成mp3,體積基本變成原來的10分之一,那麼如下這樣作。。。。
‧ 把lame主文件放到系統檔案夾下面,方便使用。
‧ 建個bat文件,內容如下:
For /r d:\wave %%i in (*.wav) do lame --preset mw-us -m m %%i c:\%%~pni.mp3
‧ do前面是For 指令的循環,/r表示對子資料夾遞回執行,找到每個wav文件,將完整的檔案名送到變數%i,%%i的寫法是因為bat的需要。
‧ do後面是對每個找到的文件進行壓縮,參數--preset mw-us是壓成40Kbps,基本上與源文件沒什麼區別,參數-m m表示壓成單聲道。
‧ %%~pni表示只要每個文件的路徑(不包括磁碟代號)和檔案名部分(不包括副檔名)。
----------------------------------------------------------------------------------------------- |
|