find + grep + (customized)sedの話

Linuxコマンドで、find, grep, sedを組み合わせることで柔軟な置換が可能となる。
例えば、

find . -name "*.txt" | grep -l "hoge" | xargs -L 1 sed -i -e "s/hoge/fuga/g"

これで、hogeと書いてある*.txtを検索、すべてfugaに書き換える。


しかし、置換したファイルを別名で保存するときには少し厄介なことになる。
sedで別名保存するときには sed -e "..." base.txt > base_2.txt
というように記載するが、これがxargsと相性がよくない。
例えば、

find . -name "*.txt" | sed "s/\(.*\).txt/\1.txt > \1_2.txt" | xargs -L 1 sed -i -e "s/hoge/fuga/g"

これはエラーとなる。xargsがsedにわたす「>」をクォーテーションで囲ってしまうために、
ファイル名と認識されるからだ(と思う)。


これでは不便なので、sedの改造版xsedを用意する。
といっても、適当にシェルスクリプトで書くだけだが。

#!/bin/sh
#xsed (chmodで実行可能にしておくこと)
`sed ${@:1:($#-1)} > ${!#}`


sed

sed "str" A.txt > B.txt

と書くところを、

xsed "str" A.txt B.txt

と書くだけ。


これでxargsで渡した際も

find . -name "*.txt" | sed "s/\(.*\).txt/\1.txt \1_2.txt" | xargs -L 1 xsed -e "s/hoge/fuga/g"

こんな感じで別名保存ができるようになった。


(もっといい方法があるのだろうが、思いつかなかったのでこれで運用)