2011年9月24日 星期六

DOS指令操作: CMD與TXT的互動

今天研究的是如何用cmd在既有的 txt 檔案內以關鍵字的方式對整行內容做操作。
例:
ming.txt
有一天,小明、小華、小美一起坐飛機出去玩,
但是飛機故障了,機上只有兩個降落傘,
小明搶了一個跳了下去,可是小華卻一直笑,
小美說:已經剩下一個降落傘了妳還笑得出來,
小華說:小明拿到我的書包了。

我的需求是要設定可自訂的多個關鍵字來對整行操作 如: 刪除所有含關鍵字的一整行內文。


關於寫入操作

for /f "tokens=*" %a in (22.txt) do echo %a>11.txt
for /f "tokens=*" %a in (22.txt) do echo %a>>11.txt

上面兩行的差別是,">" 會以新內容將舊內容覆蓋;">>" 為將新內容續寫至舊內容下。
若11.txt不存在則創建它。

for /f "tokens=*" %a
以 for 進行迴圈並對內容逐行操作,tokens=* 意思是對該行所有段落都執行,最後將執行結果存入變數 %a。

in (22.txt)
括號內限定 for 做迴圈的範圍,如檔名含有空格則須以雙引號括住。
do echo %a>11.txt

do 後指示要對先前的 %a 進行什麼操作,echo %a>11.txt 意思是將 in 中的範圍傾印至 11.txt 中。

關於過濾操作
在尋找方法時發現 find 加上參數 /v 可以過濾掉含有關鍵字的行數;
如我輸入 find /v "小華" ming.txt
則將輸出:
---------- MING.TXT
但是飛機故障了,機上只有兩個降落傘,
小美說:已經剩下一個降落傘了妳還笑得出來,
將 find /v 加上輸出的寫法為:
for /f "tokens=*" %a in ('find /v "小華" "ming.txt"') do @echo %a>>result.txt
輸出的結果會是將不含"小華"的行數寫入 result.txt 中。

結果
找了一下午對多關鍵字比對還是沒有頭緒,只好上網找能達到相同結果的軟體幫忙,
後來找到 Text Filter
介紹:
Text Filter 實用的文字檔案內容搜尋及過濾工具(免安裝)


Text Filter 提供三種搜尋方式,Navie Query 就是我們現在常用的關鍵字模式。




在切換成正規表示式後就能在上方的搜尋欄以 "|" 符號來設定多組關鍵字。




最後再在 View 將選項調成 Hide Unmatched Lines 就能達成篩選的目的!




設定完關鍵字後可以在 File>Export>Filter results 將結果匯出成文字檔。





有个.txt文本里的内容是
123
123
123
用什么命令可以让它变成
1234a
1234a
1234a


@echo off
set b=4a
for /f "delims=" %%i in 1.txt do echo %%i%b%>>"%userprofile% \D:\1.txt

參考引用:
cmd如何修改文件?  - 裡面討論到延時啟動與文件內容存入變數的寫法。
BAT:批處理教學(上) - 要寫成 bat 會用到的一些語法教學
BAT:批處理教學(下) - 組合指令(&) 與管道指令( | )  好像用這個就能達成今天的目標!
                                               改天再來研究!

2011年9月17日 星期六

DOS 指令操作: 批次更改檔案名稱


今天的問題是要批次更改一個資料夾內的檔案名稱,首先 Win+R 後輸入 "cmd" 開啟命令提示字元視窗。

切換到目標資料夾
cd 指令是切換"資料夾"名稱,在一般情況下是不改變磁碟目錄的;所以輸入 cd F:\ 只會跳一下 "F:"後又再跳回"C:",這時有兩種方法可以切換磁碟:
1. 直接輸入磁碟代號 ex.) d:
2. cd /d 磁碟代號; 這是告訴提示符切換目錄的同時也改變磁碟 ex.) cd /d d: 

確認目標檔案
如果目標資料夾內混雜著其他不需要修改的檔案,在開始修改檔案名稱之前可以先使用指令過濾一下目標檔案,否則改錯了可能會讓情況不太好收拾。
dir [/w][/b] 檔案名稱/b 使用簡化版本清單,不顯示檔案詳細資料/w 使用寬版簡化清單,不會讓你的卷軸向下跳太多都是檔案名稱的部分,可以使用萬用字元來過濾,"*"代表 零到任意多個隨意字元;"?"代表 零到一個隨意字元,但?做為第一個字母不得為0假設今天我的資料夾內有 a01.txt , a02.wmv , b03.doc , a.txt接著輸入 dir a*.* 將顯示 a01.txt, a02.wmvdir *.txt 將顯示 a01.txt, a.txtdir ?.* / ??.* 將顯示 a.txtdir ?a.* 將顯示 找不到檔案 ("?" 做為第一個字母必為1個字元)dir ?0*.* 除了 a.txt 以外都會被顯示
修改檔案名稱
ren 為 dos 內修改檔案及資料夾名稱的指令。用法為:
ren 目標資料夾或檔案名稱 最終資料夾或檔案名稱
以上面的四個檔案來繼續舉個例:假設今天我的資料夾內有 a01.txt , a02.wmv , b03.doc , a.txt先切換路徑到我的資料夾接著輸入 ren a.txt a04.txt 就會把 a.txt 修改成 a04.txt若要修改大量的檔案就要使用萬用字元的幫忙,輸入 ren a*.* a*.abc就會變成 a01.abc, a02.abc , b03.doc a.abc輸入 ren *.* *.txt 就會將所有的檔案副檔名更改成 txt
修改無規則檔案的第一個字元
在修改一般規則性檔案時,例如整個資料夾連續的
*a##.jpg (*代表任意數量字母,##代表數字)
時,可以下 ren *a*.jpg a*.jpg,即可去掉第一個字母。
但當我們要修改的是無規則檔名第一個字元時,問題就來了。假設今天我的資料夾內有
[001].jpg , [002].jpg , ... , [999].jpg
依照上面的邏輯來說,我們應該是輸入
ren x*.jpg *.jpg
但第二個參數 "*.jpg" 的萬用字元已經包含整個檔案的檔名,所以執行這個指令,是不會有任何變動的。我們還是可以用土法煉鋼下
ren [0*.jpg 0*.jpg、
ren [1*.jpg 1*.jpg
重複9次來完成這個動作,但若想要用一行指令來解決的話就得再加上其他的指令來輔助修改檔案。
for /f "tokens=1* delims=[" %a in ('dir /b [*.jpg') do ren [%a %a
for 的一般用法 FOR %variable IN ('set') DO 命令 [command-parameters]for /f 的用法 FOR /F ["options"] %variable IN (`command`) DO command [command-parameters]
"tokens=1* delims=[ "%a
delims=[ 以 "[" 做為目標取樣的分隔符號,分隔符號將不會被記入。tokens=1* 以 delims 指定的符號分隔並取第一個部分與之後的所有字元,等同tokens=1,*for /f 內的token參數預設為1,所以若只要取第一部分可省略tokens=2,3* 以 delims 指定的符號分隔並取第一,二個部分與之後的所有字元
%a 指定取樣後的變數名稱
in ('dir /b [*.jpg')
單引號內的指令限制我要改變的檔案名稱範圍
do ren [%a %a
對每個 in(set) 內的檔案執行 do 後的指令。在這裡如果下 do ren [*.* %a 會使檔案錯亂
若只是要修改第一個字元的話以上的指令可以簡化成 
for /f "delims=[" %a in ('dir /b [*.jpg') do ren [%a %a 
若是要修改檔案中的特定字元,就要加上tokens 的幫助 
for /f "tokens=1* delims=x" %a in ('dir /b *x*.jpg') do ren %ax%b %a%b 
概念: 以x分開檔名,tokens 取第一與其後之部分後,重新命名將x拿掉

批次檔製作
--以下複製--
@echo off
for /f "tokens=1* delims=x" %%a in ('dir /b *x*.bmp') do ren %%ax%%b %%a%%b
pause
--以上複製--
1. 在目標資料夾新增一個純文字檔案,副檔名更改為 *.bat。 
2. 在此bat檔案上按右鍵選擇編輯,將指令中的x更改為要替換的字元,in 中輸入過濾條件,do 中將x更改為要替換的字元後存檔關閉。 
3. 執行。若資料重要可以先創建一個實驗資料夾看看修改的結果是否正確再行套用。



2.
@echo off
for %%a in (*.bmp) do (
set "file=%%a"
call ren "%%a" "%%file:x=%%")

參考引用:
CD、MD、RD、DIR 的使用
REN、TYPE、ATTRIB 的使用
for指令太強了 - for 更深的進階應用
教學 - DOS技巧100例 - DOS指令與實例操作