シェルからファイルの一括置換の実行を素振りしてみる。その1
http://d.hatena.ne.jp/agt/20071101#p1のコメント欄で教えてもらったコマンドを今後のために「素振り」してみた。
まずid:dragon3さんのやつ。
dragon3『MavenReleasePlugin使えばいいじゃん、ていうのは置いておいて。
find . -name ’*.xml’ -print | xargs grep -l ”0.9.2-SNAPSHOT” | xargs perl -pi -e ’s/0¥.9¥.2-SNAPSHOT/0¥.9¥.2/g’
とかどうっすか?』
パイプでコマンドがつないであるので、ひとつづつ試してみる。まずは最初のコマンド。
find . -name '*.xml' -print
これは簡単。拡張子がxmlのファイルを探して、ファイル名をフルパスで標準出力へ出力。-printは結果を標準出力に出力するという意味だけど、なくてもとりあえず標準出力に出ているみたい。
実行結果はこんな感じ。
./cubby/pom.xml ./cubby/src/site/site.xml ./cubby-archetype/pom.xml ./cubby-archetype/src/main/resources/archetype-resources/pom.xml ./cubby-archetype/src/main/resources/archetype-resources/src/main/webapp/WEB-INF/web.xml ./cubby-archetype/src/main/resources/META-INF/maven/archetype.xml ./cubby-archetype/src/site/site.xml ./cubby-dist/build.xml ./cubby-dist/pom.xml ./cubby-dist/site/site.xml ./cubby-skin/pom.xml ./cubby-skin/src/site/site.xml ./cubby-tomcat55-support/pom.xml ./cubby-tomcat55-support/src/site/site.xml ./pom.xml ./src/site/site.xml
さて、次のコマンドはxargsとgrep。
xargs grep -l "0.9.2-SNAPSHOT"
xargsは標準入力(findの結果)を改行か空白で区切って順番に次のコマンド(grep)に引数として渡して処理していくコマンド。grepは文字列の検索で、-lを指定するとファイル名のみ出力という意味。結果は以下。「-exec」でも同じことができるみたいだけどfind + xargs と find -exec の使い分け)を見るとあえて-execを使う場面はあまりなさそう。
-lなしの実行結果。
find . -name '*.xml' -print | xargs grep "0.9.2-SNAPSHOT" ./cubby/pom.xml: <version>0.9.2-SNAPSHOT</version> ./cubby/src/site/site.xml: <version>0.9.2-SNAPSHOT</version> ./cubby-archetype/pom.xml: <version>0.9.2-SNAPSHOT</version> ./cubby-archetype/src/main/resources/archetype-resources/pom.xml: <version>0.9.1</version> ./cubby-archetype/src/site/site.xml: <version>0.9.2-SNAPSHOT</version> ./cubby-dist/pom.xml: <version>0.9.2-SNAPSHOT</version> ./cubby-dist/site/site.xml: <version>0.9.2-SNAPSHOT</version> ./cubby-skin/pom.xml: <version>0.9.2-SNAPSHOT</version> ./cubby-skin/src/site/site.xml: <version>0.9.2-SNAPSHOT</version> ./cubby-tomcat55-support/pom.xml: <version>0.9.2-SNAPSHOT</version> ./cubby-tomcat55-support/src/site/site.xml: <version>0.9.2-SNAPSHOT</version> ./pom.xml: <version>0.9.2-SNAPSHOT</version> ./src/site/site.xml: <version>0.9.2-SNAPSHOT</version>
-lありの実行結果。
find . -name '*.xml' -print | xargs grep -l "0.9.2-SNAPSHOT" ./cubby/pom.xml ./cubby/src/site/site.xml ./cubby-archetype/pom.xml ./cubby-archetype/src/main/resources/archetype-resources/pom.xml ./cubby-archetype/src/site/site.xml ./cubby-dist/pom.xml ./cubby-dist/site/site.xml ./cubby-skin/pom.xml ./cubby-skin/src/site/site.xml ./cubby-tomcat55-support/pom.xml ./cubby-tomcat55-support/src/site/site.xml ./pom.xml ./src/site/site.xml
対象のファイル一覧ができたところで、最後のコマンドはperl。
xargs perl -pi -e 's/0\.9\.2-SNAPSHOT/0\.9\.2/g'
xargsはさっきと同じ意味で、find+grepの結果のファイル名をperlコマンドに引数として渡すという意味。オプションには以下の意味があるみたい。-p便利。
- -p ファイル名が引数として与えられた場合にファイルから読み込み、全行を処理する。
- -i Webで調べたら「ファイルの内容を置換する」って書いてあるけど、おそらく「引数で指定されたファイルを、標準出力の結果と置換する」という意味だと思う。
- -e 指定された文字列をプログラムとして実行する。
例えば、カレントディレクトにあるpom.xmlファイルを置換したいときは以下でできました。
perl -pi -e 's/0\.9\.2-SNAPSHOT/0\.9\.2/g' ./pom.xml
以上、勉強になりました。
RR 『t=/tmp/agt-$$ v=0.9.2; for i in `find . -name ¥*.xml -exec grep -q $v-SNAPSHOT {} ¥; -print` ; do cat $i | sed -e ”s/$v-SNAPSHOT/$v/” > $t; mv -i $t $i ; done;』
RRさんのやつも今度「素振り」してみます。