- 帖子
- 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表示只要每個文件的路徑(不包括磁碟代號)和檔案名部分(不包括副檔名)。
----------------------------------------------------------------------------------------------- |
|