GNU findで正規表現を使いたい場合、デフォルトはエスケープがたくさん必要で使い勝手の悪いemacs正規表現です。というところまでは以前調べました。
- findの正規表現(regextype) - ctrl-alt-moccos
- -regextype で正規表現のタイプを変更できる
毎回-regextype posix-egrepと打つなど本末転倒なので、findとタイプして呼び出すだけで自然についてきて欲しい。そこでまずは、安直にシェルのaliasで解決しようとしました。
alias find='find -regextype posix-egrep'
これで安心と思いきや、探索先のパスを指定すると…つまりカレントディレクトリ以外から探そうとすると動きません。
(上記aliasのfind) % find ./hoge -regex ".*\.(h|cpp)" find: paths must precede expression: ../ Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
パスは、-regexや-regextypeより前に置けと。エイリアスを使わない形で書くと、次のような形式が正しいようです。
% find ./hoge -regextype posix-egrep -regex ".*\.(h|cpp)"
それならば、最初の引数だけ前の方に動かすシェル関数でも書くか、と次に思いました。簡単な検索ならばそれでOKですが、まだ問題があります。Usageに示されているように、パスよりも前に書く必要のあるオプションがあり、これを真面目に考えるとさらに面倒になります。
% find ./hoge -L -regex ".*\.(h|cpp)" find: unknown predicate `-L'
これらのオプションは0個以上で不定なので、引数の位置で判断するわけにいかないし、かといってパスを字面から判断するのもなかなか困難でしょう。
-D (デバッグ) と -Olevel (検査の最適化)は使わないと割り切り、-H -L -P(シンボリック関係のオプション)があったら-regextypeの前方に動かして、残りの引数の先頭が-で始まらない場合(=パス)をそれらと-regextypeの間に動かす(という挙動をするシェル関数なりスクリプトなりを書く)、あたりが手抜きの妥協点かなと思いました。
実際作ってみたら、こんな下らない事なのに意外と長く… → [Perl] GNU find wrapper to set -regextype.
私はもっと平易なものをbashで書いているのですが、検索語に、 's/(\Q.*\E|\Q*\E)/.*/g, s/\Q\d\E/[0-9]/g みたいにしています。
返信削除` 's/(\Q.*\E|\Q*\E)/.*/g, s/\Q\d\E/[0-9]/g`
少しだけPCREっぽくなるので自分の癖にあっています。Find.pmのサンプルからfindperl ってのを用意しましたが、-execdirの使いやすさ(自分にとってです)だとfindのラッパーですよね。xargsはファイル名にアポストロフィが入る場合などどうもめんどくさいです。-execdirは何も考えなくていいので。