findコマンドではまった事件、ワイルとカード文字に注意せよ!

★ぱぱにっき

いつか、娘へのプログラミング教育時に役に立つかと思い、今日会社でちょっとしたLinuxコマンド(find)ではまったことを備忘録としてメモって置こうと思います。

問題は、以下のようなコマンドでした。 

find {directory} -name ABC*

findコマンドを用いてあるディレクトリの中で先頭文字が"ABC"から始まるファイルをすべてみつけて出力する実行形式になります。

これがあるマシン環境(PC)では普通に機能したり、あるマシン環境(PC)ではエラーになったりしました。

ちなみに、{directory}はどのディレクトリから実行してもある決められたディレクトリを 確認するために絶対パスで書かれたディレクトリです。

実はこのコマンドは、端末上で直接コマンドを打ち込んだのではなく、あるスクリプトファイルの中に記述されたコードでして、このスクリプトを実行するとこのfindコマンドの結果期待値が正しかったり正しくなかったりしていました。

原因は知ってみれば簡単なことで、

find {directory} -name ABC*

と記述すると、シェルからfindコマンドが実行される前に、シェルがABC*を解析して展開しようとします。この展開(glob関数)がやっかいなもんで、展開ディレクトリは実行したカレントディレクトリになります。

つまり、{directory}のディレクトリの中には"ABC"から始まるファイルが複数あったわけで、{directory}のディレクトリでシェルを動かすと、

find {directory} -name ABC~1 ABC~2 ABC~3

のように展開されてfindコマンドが実行されますが、findコマンド形式違反になってしまいます。

{directory}のディレクトリでないところ("ABC"から始まるファイルがないところ)で実行すると、 展開するファイルがないため、find {directory} -name ABC*、のまま実行され、 findコマンドが、{directory}が指すディレクトリ内で"ABC"から始まるファイルを 見つけ出して展開してくれるわけです。

そもそもこのような間違いを避けるため、

find {directory} -name "ABC*"

このように書くべきだったかもしれません。

ちなみに、これだけだと、{directory}配下のサブディレクトリまでも検索対象となるため、 特定ディレクトリのみを検索するためには、

find {directory} -maxdepth 1 -name "ABC*"

のように書いたほうが間違わずに済みそうです。

※インターネットでは、サブディレクトリを除外するために、-maxdepth 0、と記述するようにと書かれたサイトもありましたが、 自分が試したCentOS 7.x GNU bash 4.x.xxxでは、maxdepthは1でないと結果が得られませんでした。