Spotlightが簡単に見つけられないファイルを発見する方法

Spotlightはあらゆるファイルを検索する能力を持っているはずなんだけど、思い付いたキーワードをそのまま入力しているだけでは、存在するはずのファイルが見つからない、という状況によく陥る。

キーワードのみで検索

例えば、最近インストールしたsaykanaコマンドをSpotlight(control-space)で検索してみると...

  • ダウンロードしたzipファイルや解凍したインストーラー、関連するwebページは見つかるけど、
  • 肝心のsaykanaコマンドはヒットしないのだ。
  • 実際にはちゃんと /usr/local/bin/SayKana として存在する。

もう一つ、bashの設定ファイルも検索してみた。

  • こちらも発見できないが、実際にはちゃんと ~/.bash_profile は存在する。

検索条件を追加する

  • 今度は、Spotlightのウィンドウ検索(control-option-space)で「システムファイルを含む」条件で検索してみた。


    • すると、saykanaコマンドがヒットした!
    • しかし、.bash_profileは見つからない...。
  • そこで、条件を変更して「ファイルの可視属性が不可視の項目」条件で検索してみた。

    • すると、.bash_profileもヒット!
      • 注意)「ファイルの可視属性が不可視の項目」にすると、検索が完了するまで相当時間がかかるし、CPUの負荷も大きかった。
  • つまり、キーワードのみで検索した時には、少なくとも以下のデフォルト条件の元で検索されているということになる。
    • 「システムファイルを含まない」
    • 「ファイルの可視属性が可視の項目」
  • しかし、これでもまだ、あらゆるファイルは検索できていない。「swapfile」で検索してみると...
    • システムファイルやファイルの可視属性の条件を変えてみても、一向にヒットしない。
    • 実際にはちゃんと /private/var/vm/swapfile0 が存在するのだが...。

ターミナルでSpotlight検索

  • 結局、GUIの環境からswapfile0をヒットすることはできなくて(アクセス権限がないため)、その検索はターミナルコマンドに委ねる必要があった。
  • mdfind を管理者権限で実行して、ようやくヒットした。
$ sudo mdfind 'kMDItemFSName == "swapfile*"'
/private/var/vm/swapfile0

mdfindの検証

  • ワイルドカード*条件と、肯定OR否定条件で、結果は異なる。
    • kMDItemSupportFileType == *
    • kMDItemSupportFileType == MDSystemFile || kMDItemSupportFileType != MDSystemFile
    • 自分勝手な予想
      • kMDItemSupportFileType == * では、kMDItemSupportFileType属性が必ず存在することが期待されるけど、
      • kMDItemSupportFileType != MDSystemFile なら、kMDItemSupportFileType属性が無くてもOKだから?
$ sudo mdfind "kMDItemFSName == '*swapfile*'c && kMDItemSupportFileType == MDSystemFile"
# 結果なし
$ sudo mdfind "kMDItemFSName == '*swapfile*'c && kMDItemSupportFileType != MDSystemFile"
/private/var/vm/swapfile0
$ sudo mdfind "kMDItemFSName == '*swapfile*'c && kMDItemSupportFileType == *"
# 結果なし
  • 管理者権限あり・無しで、結果は異なる。
$ sudo mdfind "kMDItemFSName == '*swapfile*'c"
/private/var/vm/swapfile0
$ mdfind "kMDItemFSName == '*swapfile*'c"
# 結果なし

$ ls -la /private/var/vm/swapfile0
-rw------T  1 root  wheel  67108864  6 17 14:00 /private/var/vm/swapfile0
  • 条件は || で合算できる。
  • 以下の条件は、異なる結果になる。
    • "kMDItemFSName == '*bash_*'c && (kMDItemSupportFileType == MDSystemFile || kMDItemSupportFileType != MDSystemFile)"
    • "kMDItemFSName == '*bash_*'c"
$ sudo mdfind "kMDItemFSName == '*bash_*'c && kMDItemSupportFileType == MDSystemFile"
/Users/zari/Library/Logs/CrashReporter/bash_2009-05-20-102702_zari-MacBook.crash
/Users/zari/Library/Application Support/CrashReporter/bash_10227A05-A0C8-548B-96A3-FCABD2553B5A_CrashHistory.plist
/usr/share/zsh/4.3.4/functions/_bash_completions

$ sudo mdfind "kMDItemFSName == '*bash_*'c && kMDItemSupportFileType != MDSystemFile"
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Frat.cis.k.hosei.ac.jp%2Farticle%2Flinux%2Fbash_intro.html.webhistory
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Fwww.boaro.jp%2Flinux%2Fbash%2Fbash_script.html.webhistory

$ sudo mdfind "kMDItemFSName == '*bash_*'c && (kMDItemSupportFileType == MDSystemFile || kMDItemSupportFileType != MDSystemFile)"
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Frat.cis.k.hosei.ac.jp%2Farticle%2Flinux%2Fbash_intro.html.webhistory
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Fwww.boaro.jp%2Flinux%2Fbash%2Fbash_script.html.webhistory
/Users/zari/Library/Logs/CrashReporter/bash_2009-05-20-102702_zari-MacBook.crash
/Users/zari/Library/Application Support/CrashReporter/bash_10227A05-A0C8-548B-96A3-FCABD2553B5A_CrashHistory.plist
/usr/share/zsh/4.3.4/functions/_bash_completions

$ sudo mdfind "kMDItemFSName == '*bash_*'c"
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Frat.cis.k.hosei.ac.jp%2Farticle%2Flinux%2Fbash_intro.html.webhistory
/usr/share/zsh/4.3.4/functions/_bash_completions
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Fwww.boaro.jp%2Flinux%2Fbash%2Fbash_script.html.webhistory
  • 不可視属性には、kMDItemFSInvisible == * あるいは kMDItemFSInvisible == 1 が必要
$ sudo mdfind "kMDItemFSName == '*bash_*'c && (kMDItemSupportFileType == MDSystemFile || kMDItemSupportFileType != MDSystemFile  || kMDItemFSInvisible == *)"
Password:
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Frat.cis.k.hosei.ac.jp%2Farticle%2Flinux%2Fbash_intro.html.webhistory
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Fwww.boaro.jp%2Flinux%2Fbash%2Fbash_script.html.webhistory
/Users/zari/Library/Logs/CrashReporter/bash_2009-05-20-102702_zari-MacBook.crash
/Users/zari/Library/Application Support/CrashReporter/bash_10227A05-A0C8-548B-96A3-FCABD2553B5A_CrashHistory.plist
/usr/share/zsh/4.3.4/functions/_bash_completions
/Users/zari/.bash_profile
  • 管理者権限と言えども、アクセス権がなければヒットしない。
$ mdfind "kMDItemFSName == '*bash_*'c && (kMDItemSupportFileType == MDSystemFile || kMDItemSupportFileType != MDSystemFile || kMDItemFSInvisible == *)"
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Frat.cis.k.hosei.ac.jp%2Farticle%2Flinux%2Fbash_intro.html.webhistory
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Fwww.boaro.jp%2Flinux%2Fbash%2Fbash_script.html.webhistory
/Users/zari/Library/Logs/CrashReporter/bash_2009-05-20-102702_zari-MacBook.crash
/Users/zari/Library/Application Support/CrashReporter/bash_10227A05-A0C8-548B-96A3-FCABD2553B5A_CrashHistory.plist
/usr/share/zsh/4.3.4/functions/_bash_completions
/Users/zari/.bash_history
/Users/zari/.bash_profile

$ ls -la ~/.bash_*
-rw-------  1 zari  staff  23963  6 17 17:04 /Users/zari/.bash_history
-rw-r--r--  1 zari  staff    231  5 19 15:37 /Users/zari/.bash_profile

属性を含めた検索ワードにする

検索キーワード中に、属性情報を含めることもできるのであった。属性名はコロン:で区切って条件として追加する。

  • 「.bash_ invisible:1」
      • 注意)「invisible:1」にすると、検索が完了するまで相当時間がかかるし、CPUの負荷も大きかった。

ところが、「システムファイルを含む」という属性については、どのようにキーワードに含めて表現するのか分からなかった...。以下のように書いてみたが、システムファイルは検索されない...。

  • 「saykana kMDItemSupportFileType:MDSystemFile」

検索ウィンドウの条件をAND、OR、NOTで繋ぐ

  • 今まで知らなかったが、検索ウィンドウで複数の条件を利用する時、AND、OR、NOTを指定できる。
  • optionキーを押しながら + ボタン( … に変化する)をクリックすればOK。

  • これを利用すれば、かなり複雑な条件でも検索できそう。
  • デフォルトでは複数の条件はANDで繋げて評価されるようだ。

Finderのデフォルト検索条件を変更する

  • 検索条件は、スマートフォルダとして保存しておくことができるが、検索ワードまで含めた固定された条件になってしまう。
  • 上記スマートフォルダを、Finderから command-F で検索した時のデフォルト条件として利用することもできる。
  • Finderの中身を書き換えることになるので、バックアップ等して慎重に行うべきだが、以下の手順で実現できる。
    • 好みの条件をスマートフォルダとして登録する。
    • (例:~/Library/Saved Searches/my_default_smart.savedSearch)
    • .savedSearchファイルは、テキストエディットで開いて、その詳細を確認することもできる。
$ cd /System/Library/CoreServices/Finder.app/Contents/Resources/

# 元ファイルをバックアップする
$ sudo cp default_smart.plist default_smart.plist.bak

# スマートフォルダをデフォルトにセットする
$ sudo cp ~/Library/Saved\ Searches/my_default_smart.savedSearch default_smart.plist
    • 以上で、Finderから検索した時、my_default_smart.savedSearchの条件が表示されるようになる。
$ cd /System/Library/CoreServices/Finder.app/Contents/Resources/

# Finderの初期状態に戻したい時は以下を実行する
$ sudo cp default_smart.plist.bak default_smart.plist

結論

  • GUI環境のSpotlight(control-space、control-option-space、command-F)では、全てのファイルを漏れなく検索することが出来ない。
  • ターミナルからmdfindコマンドを適切な条件で実行すれば、たぶん、全てのファイルが検索できていると考えている。(アクセス権限があれば)
  • だからGUI環境のSpotlightはダメとは考えずに、その特性を活かした検索で利用すればとても便利。
  • 辞書やホーム内の自分で作成したファイルの検索については、検索ワードのみで、素早く・確実に結果が返ってくる。
  • ファイル名でルート以下を検索する時は、以下の可能性に気を付ける。
    • 管理者権限でないとアクセスできないファイルかもしれない。
    • 大文字小文字の違いでヒットしないかもしれない。
    • 検索ワードは、前方一致・後方一致・含むのどの条件でヒットするのか?
    • システムファイルかどうか?
    • 不可視ファイルかどうか?
  • 例:ファイル名にrubyを含む全てのファイルにヒットさせる為には、以下のような検索条件を設定してみた。
$ sudo mdfind 'kMDItemFSName == "*ruby*"c && (kMDItemSupportFileType == MDSystemFile || kMDItemSupportFileType != MDSystemFile || kMDItemFSInvisible == *)'

mdfind_allコマンドを作る。

時には漏れなくファイルを検索したいこともあるけど、このままでは、また悩むことになってしまいそう。(きっと1ヵ月後には、mdfindのことなんて忘れてしまう。)そこで、mdfind_allコマンドを次回の検索に備えて作っておくことにした。

  • 以下を /usr/local/bin/mdfind_all として保存。
#! /bin/sh
echo mdfind "kMDItemFSName == '*$1*'c && (kMDItemSupportFileType == MDSystemFile || kMDItemSupportFileType != MDSystemFile || kMDItemFSInvisible == *)"
echo '管理者権限が必要なファイルを検索するには sudo で認証が必要です。'
echo Running...
echo
mdfind "kMDItemFSName == '*$1*'c && (kMDItemSupportFileType == MDSystemFile || kMDItemSupportFileType != MDSystemFile || kMDItemFSInvisible == *)"
  • 実行権限を追加して出来上がり。
$ cd /usr/local/bin
$ chmod a+x  mdfind_all
$ ls -l mdfind_all
-rwxr-xr-x@ 1 zari  wheel  104  6 17 22:55 mdfind_all
  • 利用例
    • 不可視属性も含めて検索するため時間がかかる。
    • growlnotifyを続けて実行すると良いかも。(終わった時にgrowlが教えてくれる。)
$ mdfind_all saykana; growlnotify "mdfind_all完了!"
mdfind kMDItemFSName == '*saykana*'c && (kMDItemSupportFileType == MDSystemFile || kMDItemSupportFileType != MDSystemFile || kMDItemFSInvisible == *)
管理者権限が必要なファイルを検索するには sudo で認証が必要です。
Running...

/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Fhajimemasita.blogspot.com%2F2009%2F05%2Fmacsaykana.html.webhistory
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Fwww.a-quest.com%2Faquestalk%2Fsaykana%2Findex.html.webhistory
/Users/zari/Downloads/saykana0111.pkg.zip
/Users/zari/Downloads/SayKana0111.pkg
/Library/Receipts/SayKana0111.pkg
/usr/local/bin/SayKana
/Users/zari/Library/Logs/CrashReporter/saykana_2009-06-01-051549_zari-MacBook.crash
/Users/zari/Library/Logs/CrashReporter/saykana_2009-06-01-051601_zari-MacBook.crash
/Users/zari/Library/Logs/CrashReporter/saykana_2009-05-30-115632_zari-MacBook.crash
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Fwww.a-quest.com%2Faquestalk%2Fsaykana%2Flicence_saykana.pdf.webhistory
/Users/zari/Library/Application Support/CrashReporter/saykana_10227A05-A0C8-548B-96A3-FCABD2553B5A_CrashHistory.plist
/Users/zari/Documents/saykana音声記号仕様.pdf
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Fwww.google.com%2Fsearch?q=saykana&ie=UTF-8&oe=UTF-8.webhistory
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Fwww.a-quest.com%2Faquestalk%2Fsaykana%2F.webhistory
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Fwww.google.com%2Fsearch?client=safari&rls=ja-jp&q=saykana&ie=UTF-8&oe=UTF-8.webhistory
/Users/zari/Library/Scripts/SayKANA.scpt
/Users/zari/Library/Logs/CrashReporter/saykana_2009-06-02-115112_zari-MacBook.crash
$ mdfind_all bash_; growlnotify "mdfind_all完了!"
mdfind kMDItemFSName == '*bash_*'c && (kMDItemSupportFileType == MDSystemFile || kMDItemSupportFileType != MDSystemFile || kMDItemFSInvisible == *)
管理者権限が必要なファイルを検索するには sudo で認証が必要です。
Running...

/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Frat.cis.k.hosei.ac.jp%2Farticle%2Flinux%2Fbash_intro.html.webhistory
/Users/zari/Library/Caches/Metadata/Safari/History/http:%2F%2Fwww.boaro.jp%2Flinux%2Fbash%2Fbash_script.html.webhistory
/Users/zari/Library/Logs/CrashReporter/bash_2009-05-20-102702_zari-MacBook.crash
/Users/zari/Library/Application Support/CrashReporter/bash_10227A05-A0C8-548B-96A3-FCABD2553B5A_CrashHistory.plist
/usr/share/zsh/4.3.4/functions/_bash_completions
/Users/zari/.bash_history
/Users/zari/.bash_profile
$ sudo mdfind_all swapfile; growlnotify "mdfind_all完了!"
Password:
mdfind kMDItemFSName == '*swapfile*'c && (kMDItemSupportFileType == MDSystemFile || kMDItemSupportFileType != MDSystemFile || kMDItemFSInvisible == *)
管理者権限が必要なファイルを検索するには sudo で認証が必要です。
Running...

/private/var/vm/swapfile0

メタデータ属性を確認する

  • mdlsコマンドで、ファイルやフォルダのメタデータ属性の詳細を確認できる。
$ mdls /usr/local/bin/SayKana
kMDItemContentCreationDate     = 2009-05-16 14:55:47 +0900
kMDItemContentModificationDate = 2009-05-16 14:55:47 +0900
kMDItemContentType             = "public.unix-executable"
kMDItemContentTypeTree         = (
    "public.unix-executable",
    "public.data",
    "public.item",
    "public.executable"
)
kMDItemDisplayName             = "SayKana"
kMDItemFSContentChangeDate     = 2009-05-16 14:55:47 +0900
kMDItemFSCreationDate          = 2009-05-16 14:55:47 +0900
kMDItemFSCreatorCode           = ""
kMDItemFSFinderFlags           = 0
kMDItemFSHasCustomIcon         = 0
kMDItemFSInvisible             = 0
kMDItemFSIsExtensionHidden     = 0
kMDItemFSIsStationery          = 0
kMDItemFSLabel                 = 0
kMDItemFSName                  = "SayKana"
kMDItemFSNodeCount             = 0
kMDItemFSOwnerGroupID          = 80
kMDItemFSOwnerUserID           = 0
kMDItemFSSize                  = 422764
kMDItemFSTypeCode              = ""
kMDItemKind                    = "Unix 実行ファイル"
kMDItemLastUsedDate            = 2009-05-16 14:55:47 +0900
kMDItemSupportFileType         = (
    MDSystemFile
)
kMDItemUsedDates               = (
    2009-05-16 00:00:00 +0900
)
$ sudo mdls /private/var/vm/swapfile0
kMDItemContentType         = ""
kMDItemFSContentChangeDate = 2009-06-17 14:00:59 +0900
kMDItemFSCreationDate      = 2009-06-17 14:00:59 +0900
kMDItemFSCreatorCode       = ""
kMDItemFSFinderFlags       = 0
kMDItemFSHasCustomIcon     = 0
kMDItemFSInvisible         = 0
kMDItemFSIsExtensionHidden = 0
kMDItemFSIsStationery      = 0
kMDItemFSLabel             = 0
kMDItemFSName              = "swapfile0"
kMDItemFSNodeCount         = 0
kMDItemFSOwnerGroupID      = 0
kMDItemFSOwnerUserID       = 0
kMDItemFSSize              = 67108864
kMDItemFSTypeCode          = ""