見出し画像

Macのターミナルからファイルに関連付けられたアプリ一覧を取得する

前提

とあるプログラムを組むうえで、Macで「ファイルに関連付けられたアプリケーション」をターミナルから取得する必要がありました。
Finderでいうところのこれです。

デフォルトのアプリケーションを取得するだけであればmdlsコマンドやdutiコマンドを用いれば簡単なのですが、今回欲しいのは選択できるアプリケーションのリストです。

調べたところ、Macでは拡張子ごとのアプリケーションの関連付けはLaunch Servicesで管理されており、lsregisterという実行ファイルを-dumpオプション付きで実行することで現在の設定を取得できるそうです。
ただ、あまりにも表示される内容が多いのでテキストファイルへリダイレクトしたところ、26MBものサイズでした。頻繁に処理を行う場合にはかなり負荷が高くなりますね。

$ lsregister -dump > lsregister-dump.txt

あと普通にここから関連付けされたアプリケーションを持ってくる方法がわかりませんでした。

なので別案を調べます。

本題

???「これ実現可能性あります? 同様の事象は少なくとも日本語で調べた限り見当たりませんが」

???

とりあえず、同様の事象は少なくとも日本語で調べた限り見当たりません。

しかし、こういうのは英語で調べたほうが関連情報がヒットする可能性が高いのでそれっぽい単語でググった結果、海外のQ&Aサイトで類似する質問がありました。

覗いてみたところ、SwiftのLSCopyAllRoleHandlersForContentTypeという関数を用いればスマートにリストを持ってこれそうです。

しかし、こちらは公式ドキュメントを見ると分かる通り、macOS 12.0をもって廃止されている関数でした。

Locates an array of bundle identifiers for apps capable of handling a specified content type with the specified roles.

macOS 10.4–12.0 Deprecated

https://developer.apple.com/documentation/coreservices/1448020-lscopyallrolehandlersforcontentt

もう少し調べてみると、AppKitでURLsForApplicationsToOpenURLという似たようなメソッドが存在していたので、それをAppleScript経由で使用することで実装を行います。

実装

use AppleScript version "2.4" 
use scripting additions

use framework "AppKit"
set filePath to "実際のファイルパス"
set fileURL to current application's NSURL's fileURLWithPath:filePath

set workspace to current application's NSWorkspace's sharedWorkspace()
set appsArray to workspace's URLsForApplicationsToOpenURL:fileURL

set resultList to {}
repeat with appURL in appsArray
	set end of resultList to appURL's lastPathComponent() as text
end repeat
return resultList

試しにpngファイルのパスを指定した結果が以下です。

こちらのAppleScriptをosascriptコマンドで実行することで無事にターミナルでファイルに関連付けられたアプリケーションを取得することができました。

ちなみに今回はアプリケーション名のみを取得していますが、アプリケーションのフルパスまで併せて取得したい場合は、NSURLクラスのlastPathComponentプロパティを使わずにpathプロパティを用いるだけでOKです。

use AppleScript version "2.4" 
use scripting additions

use framework "AppKit"
set filePath to "実際のファイルパス"
set fileURL to current application's NSURL's fileURLWithPath:filePath

set workspace to current application's NSWorkspace's sharedWorkspace()
set appsArray to workspace's URLsForApplicationsToOpenURL:fileURL

set resultList to {}
repeat with appURL in appsArray
	-- set end of resultList to appURL's lastPathComponent() as text
	set end of resultList to appURL's |path|() as text
end repeat
return resultList


この記事が気に入ったらサポートをしてみませんか?