用 UNIX,只要真的弄熟 findsedxargs 等工具,不用學什麼 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.vcprojb.vcprojc.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

其中,單數行是 sedp 指令印出來的,雙數行是 s/// 指令印出來的。

如此一番,將找到的路徑,兩行為一組,餵給 xargs -n2 一次收兩行,就可以組合出如下的指令:

mv a.vcproj a.vc9.vcproj
mv b.vcproj b.vc9.vcproj
mv c.vcproj c.vc9.vcproj

新的更換檔名的方法,字數更少,亦不限於只能更換延伸檔名,彈性更佳。


  1. -I 是 FreeBSD 上的 xargs 的參數,在 Linux 上,參數名稱不一樣。