用 find、sed、xargs 及 mv 換檔名
用 UNIX,只要真的弄熟 find、sed、xargs 等工具,不用學什麼 scripting language,就已經可以處理大部分複雜的需求了。
話說我以前要更換延伸檔名的時候,指令大概都是這麼下的:
SHELL> find . -type f -name '*.vcproj' \
| sed -e 's/\.vcproj$//' \
| xargs -n 1 -I @ mv @.vcproj @.vc9.vcproj \
;
首先先用 find 把所有要被更換的檔名列出來。然後,利用 sed 把延伸檔名的部份去掉。最後,利用 xargs 的 -I 功能[1],把讀入的部份用 @ 代表,組成 mv 指令:一個用 @.vcproj 把被 sed 去掉的部份還原,組成原來的路徑,另一個則用 @.vc9.vcproj 組合成想要的新檔名。
不過,先用 sed 把延伸檔名去掉,然後再加回來,有點脫褲子放屁。在我知道,原來 sed 的 -e 參數,可以連續使用,而其 p 指令,功能是原封不動地印出輸入的東西,我才發覺,上面的指令,其實可以寫成下面這樣:
SHELL> find . -type f -name '*.vcproj' \
| sed -e p -e 's/\.vcproj$/.vc9.vcproj/' \
| xargs -n2 mv \
;
一樣是先用 find 把所有要被更換的檔名列出來。接著,利用 sed 改造,分兩個 -e 給指令:先用 p 指令印出原來的檔名,然後在用 s/// 指令,將檔名改造成我們想要的樣子。
例如,現在有 a.vcproj、b.vcproj 與 c.vcproj 三個檔案要被更名,find 會得到這樣的資料:
a.vcproj b.vcproj c.vcproj
經過 sed -e p -e 's/\.vcproj$/.vc9.vcproj/' 處理後,會變成這樣:
a.vcproj a.vc9.vcproj b.vcproj b.vc9.vcproj c.vcproj c.vc9.vcproj
其中,單數行是 sed 的 p 指令印出來的,雙數行是 s/// 指令印出來的。
如此一番,將找到的路徑,兩行為一組,餵給 xargs -n2 一次收兩行,就可以組合出如下的指令:
mv a.vcproj a.vc9.vcproj mv b.vcproj b.vc9.vcproj mv c.vcproj c.vc9.vcproj
新的更換檔名的方法,字數更少,亦不限於只能更換延伸檔名,彈性更佳。
-I是 FreeBSD 上的xargs的參數,在 Linux 上,參數名稱不一樣。 ↩



10 Comments
强大!xargs 还有这么帅的功能。前两天刚有这个需求,用 for 循环了。。
$ for i in `find . -type f -name "*.vcproj" `; do mv $i `echo $i | sed s/\(\.vcproj\)/\.vc9\1/`; done
Correction: 少了个引号
$ for i in `find . -type f -name "*.vcproj" `; do mv $i `echo $i | sed 's/\(\.vcproj\)/\.vc9\1/'`; done
如果只是單純的字串替換,用 rename 指令應該簡單一些。以文中變更延伸檔名的例子來說,指令為
rename \\\'.vcproj\\\' \\\'.vc9.vcproj\\\' *.vcproj
就可以換掉了,檔名中的任何字串都可以替換 (我常常拿它來去掉檔名中的一些贅字...)
security code 多試了幾下 指令的部份跑出一堆斜線XD
rename '.vcproj' '.vc9.vcproj' *.vcproj
letoh,
rename 大概是 Linux distro 特有的指令吧?BSD 上面找不到。:-)
jeffhung
剛剛測試一下才發現不是每個 Linux distro 都有,在我的 debian 裡的 rename 其實是 perl 附的 prename,使用方式也很簡單
rename 's/.vcproj/.vc9.vcproj/' *.vcproj
用 prename 的話可以吃 regex,用起來更方便了 (我之前只會用 emacs 的 dired 做這件事XD)
當然不看單純改名字的需求,組合 find 和 xargs 來使用還是比較強大的
因為目前手邊沒有 BSD 系統可以確認有沒有 prename,但我想用 perl 提供的工具應該會比較通用一點
letoh,
用
find、sed與xargs來達到 rename,好處是這些都是 FreeBSD base-system 裡有的東西,剛灌好就可以用。若是要用到 perl,那就多了 dependency 了。當然,perl solution 的好處是,在 Windows 上也可以用,且用法一樣。不過,
find、sed與xargs在 Windows 上,裝一下 GnuWin32 也有得用就是了。jeffhung
其實 rename script 是由 File::Rename 這套模組提供的。在安裝 cpan 模組的時候 script 會自動裝進去.
今天逛到這一篇以及相關留言討論,算是讓我這個初學者賺到了,感謝各位。
Post a Comment