mac ファイル検索高速化|索引を引く検索と走査する検索

同じMacなのに、検索が一瞬で返る場面と、進捗の輪が回り続ける場面があります。mac ファイル検索高速という言葉で調べる人が知りたいのは、速くするための隠し設定ではなく、なぜこの差が出るのかという仕組みのほうです。答えは単純で、Macの中には性質の違う2種類の検索が同居しているためです。あらかじめ作られた索引を引く検索と、ディスクを順にたどって照合する走査です。この記事では、どちらが動いているかを見分ける方法と、それぞれを速くするための具体的な手を扱います。

速い検索と遅い検索は、仕組みが別物

索引を引く検索は、Spotlight、ファインダの検索、コマンドのmdfindが該当します。これらは検索のたびにディスクを読むのではなく、あらかじめ作られたメタデータの索引に問い合わせます。索引には名前、種類、作成日と更新日、対応する形式なら本文のテキストまでが入っています。Appleの案内でも、入力しながら結果が出てくる挙動が前提として説明されています。

検索フィールドに探しているものを入力します。入力中に検索結果が表示されます。 出典: support.apple.com

打っている途中で結果が出るのは、ファイルを見に行っていないからです。索引の規模が大きくなっても、引く速さはファイル数にそれほど左右されません。

走査する検索は、コマンドのfind、grep、それに索引を使わない検索ユーティリティが該当します。こちらは指定された場所から下のディレクトリを順にたどり、1件ずつ条件と照合します。ファイルの実体を見るため結果は常に最新で、隠しファイルもシステム領域も見えますが、時間はたどった件数に比例します。ホームの下に数十万件が並んでいれば、そのぶんだけ待つことになります。

つまり、遅いと感じたときに問うべきは「Macが遅いのか」ではありません。「いま走っているのは索引を引く検索か、走査か」であり、走査なら「たどっている件数が必要以上に多くないか」です。この見分けが付くと、打つ手が4つに絞られます。索引側に寄せる、範囲を絞る、索引を直す、経路そのものを変える、の4つです。

索引を引く検索を、条件付きで使う

Spotlightの入力欄は手軽ですが、アプリもメールもWebの候補も混ざるため、ファイルだけを速く取り出す用途には向きません。同じ索引をコマンドから引くのがmdfindです。

  • mdfind -name 請求書 のように書くと、名前に語を含むものだけを索引から引きます
  • mdfind -onlyin ~/Documents 契約 のように場所を限定すると、対象を絞ったうえで索引を引きます
  • mdfind "kMDItemContentType == 'com.adobe.pdf'" のように属性で指定すると、種類や日付の条件で絞れます
  • 語だけを渡すと、名前だけでなく索引に取り込まれた本文のテキストも対象になります

いずれも走査は発生しないため、ホーム全体を対象にしても待ち時間はほとんど変わりません。ファインダの検索で範囲や条件を組み立てるより、コマンドで書くほうが再利用しやすく、結果をそのまま次の処理へ渡せます。

ファインダ側を使う場合は、検索の開始範囲を変えておきます。Finderの設定の詳細タブで、検索の開始位置を現在のフォルダに変更できます。既定はMac全体になっているため、絞り込むつもりの検索が毎回全体の問い合わせになっています。索引を引いているので致命的に遅くはならないものの、目に入る候補が増えるぶん、目的の1件に到達するまでの時間は伸びます。

走査するなら、たどる件数を減らす

走査を速くする方法は1つしかありません。たどる件数を減らすことです。方向は3つあります。開始地点を深くする、深さを制限する、途中で枝を切ることです。

  • 開始地点を深くする。find ~/Projects -name "*.csv" のように、ホームではなく実際にありそうな階層から始める
  • 深さを制限する。find . -maxdepth 3 -name "*.log" のように、何階層まで見るかを指定する。設定ファイルのように浅い場所にあるものは、これだけで対象が大きく減る
  • 枝を切る。find . -name node_modules -prune -o -name "*.ts" -print のように、たどらないディレクトリを先に外す。依存パッケージやビルド結果は、件数の大半を占めていながら探す対象ではないことが多い

道具そのものを替える手もあります。fdとripgrepは複数のスレッドで走査するため、同じ範囲でもfindやgrepより待ち時間が短くなります。ただし既定値が違います。どちらも初期状態では隠しファイルと、.gitignore に書かれたファイルを飛ばします。ripgrepなら -uu、fdなら -HI を付けると、この既定が外れて全部を見に行きます。ソースコードの外を探しているのに結果が出ないときは、ほとんどがこの既定値によるものです。

macOSには locate も入っています。こちらは週次の定期処理で作られるデータベースを引く仕組みですが、そのデータベースが作られていないと使えません。実行して、データベースが小さすぎるという趣旨の警告が出る場合は、まだ作られていない状態です。

索引が仕事をしていないときの点検

索引を引く検索が遅い、あるいは何も返さないときは、索引側が止まっている可能性があります。作り直す前に、状態を確認する順番があります。

  • mdutil -s / でボリュームの索引の状態を表示する。無効になっていれば、検索が返らない理由はそこにある
  • システム設定のSpotlightにある検索のプライバシーの一覧を見る。ここに入っているフォルダやディスクは、結果から完全に外れる
  • フォルダ名が .noindex で終わっていないかを見る。この接尾辞が付いたフォルダは索引の対象外になる
  • 外付けディスクを接続した直後かどうかを見る。接続後は索引の作成が背後で走り、その間の結果は不完全になる

この4つを通してから、索引の作り直しを検討します。sudo mdutil -E / は索引を消して作り直しますが、処理は背後で進み、内蔵ディスクの容量と書類の数によっては数十分から数時間かかります。その間の検索結果は不完全なままなので、原因が別のところにあった場合は待ち時間だけが残ります。

ネットワーク共有は事情が違います。共有先のサーバが検索の仕組みに対応していない場合、Macは索引を引けず、共有越しに1件ずつ照合する形になります。回線を1往復しながらの走査になるため、同じ件数でもローカルより大きく遅くなります。共有上の資料を頻繁に探すなら、探す対象だけをローカルに置くか、サーバ側の検索機能を使うほうが速い場合があります。

内容で探すときは、道具の性格が分かれる

名前ではなく中身で探す場合、速度差はさらに大きくなります。mdfindに語を渡す方法は、索引に取り込まれた本文を引くので一瞬で返ります。ただし対象は、取り込みの仕組みが対応している形式に限られます。プレーンテキスト、PDFの多く、書類アプリの形式などです。

grepやripgrepは、ファイルを開いて読みます。形式を選ばず、索引の外にあるものも読めますが、時間はファイルの総量に比例します。大きなリポジトリの中で rg 検索語 が数秒かかるのは、実際にその量を読んでいるためです。

使い分けの目安は2つです。書類の中身を探すなら索引側、コードやログや設定ファイルの中身を探すなら走査側です。前者は索引が対応する形式が多く、後者は索引の対象外に置かれていることが多いためです。

走査で中身を探すときは、読む量を先に減らします。rg 検索語 --glob "*.ts" のように対象の拡張子を絞る、rg -n --max-filesize 1M 検索語 のように大きなファイルを外す、といった指定で、読み込むバイト数そのものが減ります。ログのように1件が巨大なファイルが混ざっている場合、この指定があるかどうかで待ち時間が変わります。逆に、圧縮されたファイルやディスクイメージの中は、索引側も走査側も開くまで対象になりません。中身を探す前に、展開するかマウントする工程が要ります。

名前の付け方が、検索の速さを決めている

検索を速くする手段として見落とされやすいのが、探される側の名前です。索引は名前を語の単位で持っているため、名前に意味のある語が入っていれば、範囲を広く取ったまま1回で絞り込めます。逆に、書き出しツールが付けた連番だけの名前が並んでいると、名前では絞れず、日付や種類の条件を重ねることになり、目で選ぶ工程が残ります。

具体的には、先頭に日付、次に案件や内容を表す語、という並びにしておくと、名前順の並びと検索の両方が同時に効きます。既存のファイルはFinderの一括リネームでまとめて直せます。複数選択して右クリックから名前の変更を選ぶと、文字列の置換、先頭や末尾への追加、連番での振り直しが選べます。

もう1つの効果は、後の工程が単純になることです。空白を含まない名前にしておくと、検索結果のパスをそのままコマンドへ渡せます。空白があると引用符の扱いが要るため、結果を受け取ってから処理するまでに手が1つ増えます。

同じ検索を繰り返し組み立てないことも、体感の速さに効きます。同じ条件を3回以上打っているなら、その形は保存できます。コマンド側なら、範囲の指定と除外する枝と付けるオプションをまとめた別名を作っておけば、次からは短い1語で同じ検索が走ります。ファインダ側なら、ファイルメニューの新規スマートフォルダで条件を保存でき、開くたびに同じ条件で引き直されます。1回あたりの検索が速くなるわけではありませんが、条件を組み立て直す時間が消えます。検索に時間がかかっていると感じている場面の一部は、実際には条件を毎回思い出して打ち直す時間です。

検索の速さより、検索の後の工程のほうが重い

コマンドの選び方と範囲の絞り方を直すと、検索そのものの待ち時間はかなり短くなります。それでも作業全体が速くなったと感じにくいことがあります。時間が消えているのが、検索の後の工程だからです。

流れを数えると形が見えます。ファインダの検索で目的のファイルが出る。それをコマンドで処理したいので、選択してパスをコピーし、窓を切り替えて貼り付ける。逆にコマンドで見つけたパスの中身を目で確かめたいときは、また窓を戻す。1回あたりは数秒ですが、1日に何十回も繰り返される動作なので、合計では検索の待ち時間を上回ります。

ここに効くのがフォルダとターミナルとAIが同じ窓にあるという配置です。検索結果の一覧とコマンドの作業ディレクトリが同じであれば、パスのコピーと窓の切り替えがまるごと消えます。この配置で何ができるかはできることにまとまっており、2画面型やターミナル常駐型など別の課題を解いている道具との違いは他のファイル管理との比較で見比べられます。費用の条件を先に知りたい場合は料金を、動作環境や制限を確かめたい場合はよくある質問を見てから判断できます。外に出ているあいだに結果だけ確認したいときの動きはiPhone・iPadから続きをにあります。

まず1週間、検索の後に窓を切り替えた回数を数えることをすすめます。回数が少ないなら、この記事の前半にある範囲の絞り方だけで足ります。回数が多いなら、それは検索の速さの問題ではありません。

よくある質問

Spotlightは速いのに、findが遅いのはなぜ?

仕組みが違うためです。Spotlightはあらかじめ作られた索引に問い合わせるので、ファイル数が増えても引く速さはあまり変わりません。findは指定された場所から下を順にたどって1件ずつ照合するため、時間はたどった件数に比例します。findを速くするには、開始地点を深くするか、maxdepthで深さを制限するか、pruneで不要な枝を外します。

mdfindとfindはどう使い分ける?

索引に載っている条件で探すならmdfind、索引の外を探すならfindです。書類の名前や種類や本文はmdfindが速く、-onlyin で場所を絞ることもできます。隠しファイル、.noindex が付いたフォルダ、検索のプライバシーに登録された場所は索引に入っていないため、findやfdで走査するしかありません。

ripgrepやfdで一部のファイルが出てこないのはなぜ?

どちらも初期状態で隠しファイルと .gitignore に載っているファイルを飛ばすためです。ripgrepなら -uu、fdなら -HI を付けると、この既定値が外れて全部を対象にできます。ソースコード以外の場所を探しているときに取りこぼす原因の多くがこれです。

ネットワーク共有上のファイル検索が極端に遅いときは?

共有先のサーバが検索の仕組みに対応していないと、Macは索引を引けず、共有越しに1件ずつ照合する形になります。回線を往復しながらの走査になるので、同じ件数でもローカルより大きく遅くなります。よく探す資料だけをローカルに置くか、サーバ側が持っている検索機能を使うほうが速い場合があります。

記事一覧へ戻る