Mac で locate の代替として mdfind を使うことにした話
この記事でわかること
Macデフォルトのlocateコマンドが役に立たない場合、mdfindを使いましょう。
3行で
- 新しいMacでデフォルトの
locateコマンドを使おうとしたが、目的のファイルが表示されない。 - GNU findutils をインストールしたが似たような症状。
updatedbの整備をやりかけたが手間がかかる。 - Macデフォルトの
mdfindコマンドで目的が果たせることが判明。これを使うことにした。手間ナシ爆速。
記事内容
結論としては「mdfindコマンドで用が足ります」以上のことはありません。それさえわかればオッケーという人はここから読む必要はないです。
-
locateコマンドの基本動作 - Macデフォルトの
locateコマンド - GNU findutils の
locateコマンド -
mdfindは何がうれしいか
を書きます。
1. 記事前提
- ハードウェア…MacbookPro 2021, Apple M1 Pro
- 自機保守基準…システムはできるだけデフォルトで使いたい(保守コストを上げたくない)
2. locateコマンドの基本動作
locateコマンドはシステム内のファイルをファイル名で検索するコマンドです。
実行時にファイルシステムを全検索しているわけではなく、あらかじめ用意されたファイルシステム内の全ファイル名のデータベースを検索します。それによって高速な検索を可能にしています。
MacOSにもlocateコマンドがあって、あのファイルどこにあったっけ、という時に使えます。
と、思ったのです。でもそうはいかなかった。
3. Macデフォルトのlocateコマンド
仕事をしていて、あのファイルどこだったかな、とlocateで検索したのですが、うまく動きません。
- 検索結果が正常に返ってくる場合もある。システムのファイルは検索できているっぽい
- 外付けディスクにあるファイルも検索できている
- 自分のホームディレクトリにあるはずのファイルが検索結果に出てこない
このような症状で、データベースが一部欠けているようだということがわかります。何が欠けているか正確に調査特定するのは難しいですが、つまりはデータベース作成がうまくいっていないのでしょう。以下をチェックしました。
- データベース
/var/db/locate.databaseのタイムスタンプ - コマンド
/usr/libexec/locate.updatedbの仕様 - データベースシステムバックグラウンドプロセスを制御する
launchctlの設定、動作状況のチェック
正常に動いているようです。ネットを検索すると、似た症状が散見され、理由として挙がっていたのは
- データベースファイルの owner が
nobodyになっている。nobody権限で実行されていて、その権限で読めるものしかデータベースに入れられないのでは - シンボリックリンクは辿らないことになっている。Macのエイリアスなら辿る
あたりでした。
データベース作成プロセスの起動設定はシステム領域になっており、そこに手を入れるのはできればやりたくありません。また、シンボリックリンクは気軽にあちこちで使っていて、それらを全てエイリアスに変更するのは現実的ではありません。別の方法を当たることにしました。
4. GNU findutils のlocateコマンド
いずれにせよ、新しいMacにはGNUのツールをインストールするのが常なんです。仕事でGNU系のコマンドに慣れているので、Macデフォルトのコマンドはオプションが違ったりして使いづらいんですよね。
GNU findutils をインストールして、そちらの locate を使うことにしました。
この時にインストールしたコマンドライン系パッケージ一覧
- binutils
- coreutils
- diffutils
- findutils ←
locate,updatedb,findコマンドなどが入っている - gawk
- gnu-sed
- gnu-tar
- tree
ですが、こちらもうまく動かない。データベースが欠ける。findコマンドでファイル名一覧を作っているようなのですが、sudoでroot権限でデータベースを作成しても全ファイルを持ってこないので、ファイルシステムをまたげないとか、シンボリックリンクを辿れないとか、そのあたりのようです。
シンボリックリンクを辿るオプションをつけて手元のコマンドラインで実行してみると、うまく作れた様子です。
ですが、このデータベースをlocateコマンドで検索すると、ものすごく!遅かった。使い物にならないレベル。ファイル数が多いためと思われますが、これはよっぽどの時しか使わないだろうなというレスポンスタイムでした。launchctlの設定ファイルを準備する気にもなりませんでした。
5. mdfindは何が嬉しいか
いろいろ調べているうちに、mdfindを使えばいいじゃん、という記述がありました。mdfind? なにそれ?
mdfindはSpotlight の CLI
そんなものがあるのか。知らなかった。試しにいくつか検索してみたところ、データベースは正常に作れているようでちゃんと出てくる。しかも速い。これを使います。決定。
5.1. Pros
- Spotlightは普段から使ってるんだから、データベースが1系統で済むならそれに越したことはない
- 圧倒的に速い
- すでに動いているのでシステムに手を入れる必要なし
- 設定したければシステム環境設定のGUIで可能、わかりやすい
5.2. Cons
-
locateとは違うコマンドなので、当然仕様が違う - ふだんSpotlight検索をオフにしている人にはメリットはあまりない
locate の代替として使う場合は -name <filename>オプションを使うとよいでしょう。
$ mdfind -name com.apple.locate.plist
Spotlightと同じ仕様なので、オプションなしで起動するとファイルの内容までヒットします。そうしたい場合は -nameオプションなしで。
5.3. メタデータについて少し
ファイルの内容と言いましたが、正確には「メタデータ」を見ているようです(mdfindのmdは meta data)。Finderで「情報を見る」で表示されたりするあれです。
mdlsコマンドで表示できます。
$ mdls ~
$ mdfind -name com.apple.locate.plist | xargs mdls
MacOSは普段からシステムバックグラウンドでファイルシステム内の全ファイルを監視しており、メタデータを収集してインデックスを作る作業をしています。収集したメタデータは各ファイルボリュームの直下に置かれるようです。今使っているシステムでは
-
/System/Volumes/Data/.Spotlight-V100内蔵ディスク -
/Volumes/ExtremePro/.Spotlight-V100外付ディスク
こうなっています。(メタデータインデックス自身のメタデータはメタデータインデックスに入っておらず、mdfindでは出てこない仕様のようです)
mdfindの引数にはメタデータクエリを書けます。locateからだいぶ遠くなってしまったので、参考リンクを挙げてこの記事を終わりにします。
- Spotlightはどう動いているか How Does Spotlight Work?
- ファイルメタデータクエリの構文 File Metadata Query Expression Syntax
- Spotlightメタデータアトリビュート Spotlight Metadata Attributes
いずれもApple公式の開発者向けドキュメント(英文)です。
Discussion