🙌

macOSでファイルのUTIを表示するコマンドを作る

2020/09/26に公開

macOS のアプリを作成していてファイルの UTI を調べる必要があった。
以前は mdls を使っていたのだが、簡単なので今回はコマンドを作成してみた。

UTIとは

Uniform Type Identifiers の略でデータのタイプを識別する文字列。
iOS や macOS でファイルを扱うアプリを作っていると UTI の情報が必要になることがある。
詳しくは Apple のドキュメントで説明されている。

SwiftでファイルのUTIを調べる方法

URL クラスにある resourceValues(forKeys:) で調べることができる。
具体的には以下のようになる。

let url = URL(fileURLWithPath: "Path/To/File")
if let uti = try? url.resourceValues(forKeys: [.typeIdentifierKey]) {
	print(uti)
}

上記コードの typeIdentifier が UTI の文字列になる。

Swiftでターミナルからアプリを起動した場合の引数を取得する

Swift で作成したアプリをターミナルから起動した場合、コマンドの引数はCommandLine.argumentsに配列に入った形で得ることができる。今回は下記のコードで UTI を知りたいファイル名を得ることにした。

CommandLine.arguments.dropFirst().first

渡される配列にはコマンド自身が最初に入っているので最初の要素をdropFirst()で削除し、残りの引数の中で最初の要素をfirstで取得している。

これでコマンドの引数からファイル名を取得したら、URL を作成して UTI を得ればいい。

Swiftでのコマンドラインアプリの作成

Swift でコマンドラインのアプリを作成するには Xcode の Project の指定で Command Line Tool を選択すれば良いが、今回は非常に短いコードなのでターミナルでコンパイル(ビルド)することにした。

具体的にはターミナルで下記のコマンドを打てばよい。

swiftc -o puti main.swift

main.swift はコードの書かれたファイル名で puti はコマンド名。今回 print UTI と言う意味でコマンド名を puti にしてある。

コンパイルできたら試しにコマンドをうってみる。

iMac:puti paraches$ ./puti main.swift
public.swift-source

ちゃんとファイルのUTIが表示される。

後はどこからでもコマンドが使えるように /usr/local/bin にでも puti をコピーしておけば便利に使える。

cp -f puti /usr/local/bin/

Dynamic Type Identifiers

ちなみにファイルに UTI が設定されていない場合はシステムが dyn. で始まる識別子を与えてくれる。
例えばこんな値になる。

iMac:Documents paraches$ puti setup.cfg
dyn.ah62d4rv4ge80g3xh

この UTI は他のマシンでも同じになるとのことなので、ファイルを作成したアプリが UTI を指定するまでは dyn. の値を UTI の指定に使うことができる。

コード全体

非常に短いがソースコードは github においてある。

まとめ

最初にも書いたが mdls でも下記のように UTI は調べられる。

iMac:puti paraches$ mdls main.swift 
省略
kMDItemContentType                     = "public.swift-source"
省略

kMDItemContentType が調べたい UTI だ。
しかし spotlight がファイルをインデックスをしていないとこの値は "" になるので、基本的には今回作成したコマンドで調べるようにしたい。

ちなみに拡張子からもUTTypeCreatePreferredIdentifierForTag関数を使って UTI を調べることができる。
これを使ったコマンドも Github においてある。

Discussion