|
論壇說明 |
歡迎您來到『史萊姆論壇』 ^___^ 您目前正以訪客的身份瀏覽本論壇,訪客所擁有的權限將受到限制,您可以瀏覽本論壇大部份的版區與文章,但您將無法參與任何討論或是使用私人訊息與其他會員交流。若您希望擁有完整的使用權限,請註冊成為我們的一份子,註冊的程序十分簡單、快速,而且最重要的是--註冊是完全免費的! 請點擊這裡:『註冊成為我們的一份子!』 |
|
主題工具 | 顯示模式 |
2004-11-15, 04:58 PM | #1 (permalink) |
榮譽會員
|
for指令太強了
q:
for指令太強了 2000/xp下的for指令太強大了,用它可以免去很多重複勞動。 曾發過for的詳細介紹:for進階套用範例 ,裡面有說明。 [原創] 史上最強之dos指令 - "FOR" - 進階套用範例 bluebear 以前常覺得DOS的指令行功能太弱,無法象UNIX一樣可以用指令行完成非常複雜的操作。實際上,當MS從WIN2K開始將指令行增強後,已經借鑒了相當多UNIX的優點,雖然還無法做到像UNIX那麼靈活,但已可完成絕大多數的工作,比如用&&和||連接兩個(或更多)指令,由前一個的返回值來決定下一個是否執行,等等。而在這些增強中,最明顯的,就是FOR指令。 舉個例子,用適當的參數,可用FOR指令將 date /t 的輸出 從 "Sat 07/13/2002" 變成你想要的格式,比如, "2002-07-13": 程式碼: c:\>for /f "tokens=2,3,4 delims=/ " %a in ('date /t') do @echo %c-%a-%b 2002-07-13該例將在(3)中詳細說明。 0. 基本套用 簡單說,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用它可以使一些不支持萬用字元的指令對一系列文件進行操作。在WIN9X中,TYPE指令(顯示文件內容)是不支持*.txt這種格式的(WIN2K開始TYPE已支持通配)。遇到類似情況就可以用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/2001 12:50 PM 18,426 alg0925.txt 12/02/2001 04:29 AM 795 bsample.txt 04/11/2002 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/2002現在我想分離出日期部分,也就是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選項的最後一項。 再靈活一點,像本文開頭提到的,將日期用2002-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\05-18-01-A\游鴻明-下沙\游鴻明-01 下沙.mp3 g:\mp3\Archived\05-18-01-A\游鴻明-下沙\游鴻明-02 21個人.mp3 ...... g:\mp3\Archived\05-18-01-A\王菲-寓言\王菲-阿修羅.mp3 g:\mp3\Archived\05-18-01-A\王菲-寓言\王菲-彼岸花.mp3 g:\mp3\Archived\05-18-01-A\王菲-寓言\王菲-不愛我的我不愛.mp3 ......如果我只要歌名(不要路徑和".mp3"): 程式: 游鴻明-01 下沙 游鴻明-02 21個人 ...... 王菲-阿修羅 王菲-彼岸花 王菲-不愛我的我不愛 ......那麼可以用FOR指令: 程式: for /r g:\mp3 %a in (*.mp3) do @echo %~na凡是 %~ 開頭的操作符,都是檔案名的分離操作。具體請看 for /? 說明 。 本文舉的例子有些可能沒有實際用處,或可用其它辦法完成。僅用於體現FOR可以不借助其它工具,僅用DOS指令組合,就可完成相當靈活的工作。 具體請看 for /? 說明 我的電腦上有一些en的聽力虛擬光碟,來源碟的格式是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表示只要每個文件的路徑(不包括磁碟代號)和檔案名部分(不包括副檔名)。 A:Shell 指令碼提供的 for 指令確實很強,但用在這種小問題上就有點不值了。 這個問題用 foobar2000 來解決更方便,只需要點擊幾下滑鼠,根本不用去編寫指令碼。而且一樣可以保證輸出文件的目錄結構。 如使用 WSH 就更好了,功能強得多,但編寫指令碼也相對複雜得多 %%~pni很好 以前压缩的都是得到*.wav.mp3 對每個虛擬盤,執行這個bat就可以了,很快lame就將文件壓好。 for的功能真強。。。。 |
送花文章: 3,
|
2006-02-07, 12:09 AM | #2 (permalink) |
榮譽會員
|
dos下進中文目錄的方法
個人感覺很適用的技巧 1在DOS提示號下,在中文目錄所在磁碟代號(比如C碟) dir/w(空格)c:\*.*(空格)>1.TXT 2輸入edit 1.TXTEnter鍵 編輯1.TXT文件,將「某某目錄」保留下來,其他內容清除掉,並在前寫入"CD(空格)" 3按alt+F開啟file表單 選項save as...將1.TXT文件另存為"1.BAT"文件 4執行1.BAT文件,即進入C碟的「某某中文目錄」 這方法挺笨,但卻實用! 不過還是用支持中文輸入的DOS啟動碟啟始才方便。 |
__________________ |
|
送花文章: 3,
|