文字化け
Swift製のツールでFinderのラベル名を使いたくて検索した結果defaults
で取得が可能なことが分かりました。
早速試してみると
$ defaults read com.apple.Finder FavoriteTagNames
(
"",
"\\U30ec\\U30c3\\U30c9",
"\\U30aa\\U30ec\\U30f3\\U30b8",
"\\U30a4\\U30a8\\U30ed\\U30fc",
"\\U30b0\\U30ea\\U30fc\\U30f3",
"\\U30d6\\U30eb\\U30fc",
"\\U30d1\\U30fc\\U30d7\\U30eb",
"\\U30b0\\U30ec\\U30a4"
)
文字化け...
意味は分かるが自力で元に戻すのが面倒くさい。
バッドノウハウ
悪知恵を働かせた結果、JSONにして JSONDecoder or JSONSerializationを使って元に戻すというのを思いつきました。
"\\U30ec\\U30c3\\U30c9"
この部分に注目します。
これはJSONとしては正しくありません。
正しいJSONは
"\"\\u30ec\\u30c3\\u30c9\""
になります。
前後に
"
を付けて、
\\U
を
\\u
に置換すればOKということです。
出力自体は NSArray<NSString>
なPropery Listですので、PropertyListDecoder
で簡単に[String]
に変換することができます。
以下ソース
func readFinderLabels() -> [String] {
let defaultsCommand = Foundation.Process()
defaultsCommand.launchPath = "/usr/bin/defaults"
defaultsCommand.arguments = ["read", "com.apple.Finder", "FavoriteTagNames"]
let pipe = Pipe()
defaultsCommand.standardOutput = pipe
defaultsCommand.launch()
defaultsCommand.waitUntilExit()
do {
return try PropertyListDecoder()
.decode([String].self, from: pipe.fileHandleForReading.readDataToEndOfFile())
.map { $0.replacingOccurrences(of: "\\U", with: "\\u") }
.map { "\"" + $0 + "\"" }
.compactMap { $0.data(using: .utf8) }
.compactMap { try JSONSerialization.jsonObject(with: $0, options: .allowFragments) as? String }
} catch {
print(error)
return []
}
}
JSONDecoder
は文字列だけのJSONをデコードできないので、JSONSerialization
を使用しました。
JSONDecoder
を使う場合は
"[\"\\u30ec\\u30c3\\u30c9\"]"
と文字列の配列にして、そこから取り出す形になります。