UNIX/Linux の find -exec の引数にはシェルの構文を使えない.
UNIX/Linux の find コマンドの -exec アクションって,シェルを起動せずに直接コマンドを呼び出すんですね!
今まで知りませんでした (恥).
きっかけは,OKWave でのfind に関する質問.-exec の引数で,シェルの構文 `…`を使うにはどのようにエスケープすればいいのか (私も今までたまに使おうとしては挫折していた) を調べるために find のソースを少しだけ覗いてみると …あれっ,-exec でシェルを起動している気配がない!? 直接コマンドを呼び出しているみたい.それを確認するため,シェルコマンドである alias を -exec に指定して,
find . -exec alias \;
とやってみると,予想どおり次のようになった.
find: alias: そのようなファイルやディレクトリはありません
find: alias: そのようなファイルやディレクトリはありません
find: alias: そのようなファイルやディレクトリはありません
(以下略)
やっぱりシェルは呼ばれていない.だから,-execの引数にシェルの構文である `…`などを書いても実行されるわけがない.今まで (たまに) -exec でシェルの構文を使おうとして,エスケープしてみたり,引用符で囲ってみたりと悪戦苦闘してはあきらめてたけど,すべて無駄な努力だったんですね….(ToT)
-exec でシェルの構文を使いたければ,次のようにすれば可能.
find … -exec bash -c 'シェルコマンド文字列' \;
ただし,ファイルやディレクトリが1つ見つかるたびに毎回シェルが起動されるので遅くなる.さらに,シェルが起動されるたびに ~/.bashrc が実行されてしまうので,これに時間がかかると最悪.
~/.bashrc を実行しないようにするには,次のように bash の代わりにbash へのシンボリックリンクである sh を使えばよい.
find … -exec sh -c 'シェルコマンド文字列' \;
bash のマニュアルを見ると,sh -c の代わりにbash --norc -c でもいいはずなんだけど,実際やってみると ~/.bashrcが実行されてしまう.なぜ? (?_?)
シェルコマンドも使えて,かつ効率がいいのは,findで一旦シェルスクリプトを作って,それを実行することだろう.-printf を使うと,find で見つけたパス名を加工するのも簡単 (%p,%f,%h,%l など).
find … -printf "フォーマット文字列" > MyScript.sh
MyScript.sh の内容を確認し,OK ならばそれを実行する.
上記の方法でうまくいくことが確認できれば,次のようにシェルスクリプトの作成と実行を1行で書ける.
find … -printf "フォーマット文字列" | bash