グレンジ Advent Calendar 2018 6日目担当の soyo と申します。
グレンジでcocos2d-xによるゲーム開発のクライアントエンジニアをしております。
とはいえ、今回の記事はcocos2d-xとはまったく関係ありません。
簡単そうなパス変換ですが、意外と躓いてしまったので、その解決方法をまとめたいと思います。
(日本語が拙いところがありますが、ご容赦ください)
技術・環境
- macOS
- Automator
- AppleScript
- JavaScript
やりたいと思ったきっかけ
__最初は、macOSのパスをWindowsのパスに変換して共有したいだけでした__が、
その時に、一つ問題が発生しました。
どういう問題かというと、
いつもの手順は、まず共有サーバーに置いてあるファイルの詳細情報からパスをコピーします。
そして、ネットのパス変換ツールで変換して、
チャットワークで共有すれば、これで大丈夫かなと思いました。
が、アクセスできないだと?!
これは困るので、この際は自作してみようと思います!
発生した問題
濁点問題
送ったリンクをテキストエディターに貼ると、なぜか濁点がずれているようです。
ネットで調べると、Macでファイル名をコピペすると濁点と半濁点がおかしくなるという記事がありました。
この記事によると、macOSの自動化ツールAutomatorでシェルを実行すれば解決できそうですね!
マウント先のパス問題
結果、Automatorでシェル実行してコピーされたパスは以下のものとなりました…
これで、マウント先のパスが簡単に取れないことがわかりました。
でも、一応エンジニアである私が__こんなところでやられてたまるか!__
マウント先のパスを見る方法なら知っていますよ!
$ mount | grep "[デバイス名]"
これでマウント先のパスを見れます!
そして、AutomatorはAppleScriptというスクリプト言語が使えますので、
ネットで見つけたパスを変換するコードで、一応動きました!
UTF-8問題
上記のエラーについて調べた結果、
__マウント先のパスがUTF-8文字が存在する場合のみ__エラーが出ます。
$ mount | grep "[デバイス名]"
を実行すると
なんとパーセントエンコーディング?!
しかも後ろの部分(onから)は漢字のままになっています!
そのまま化けた文字が使えると思うのか!
......
使えますね。
わかったわかった、自分もこういう風に対応すれば良いでしょう。
実はAutomatorではJavaScriptも使えそうです。
JavaScriptではdecodeURIという関数が存在して、デコードができそうです。
さらに、normalize('NFC')という関数で濁点の問題も解決できそうです。
function run(input, parameters) {
return decodeURI(input).normalize('NFC');
}
これで、やっと正しい変換ができるようになりました。
ファイルの右クリックメニューからワンクリックでWindowsのパスをコピーすることができます。
最終的に実装できたもの
Automator設定
AppleScriptコード(smbのみ対応、afpはまだ)
on splitString(str, delimiter)
set OldDelims to AppleScript's text item delimiters
set AppleScript's text item delimiters to delimiter
set stringList to every text item of str
set AppleScript's text item delimiters to OldDelims
return stringList
end splitString
on getRealPath(input_file_path)
set smbPrefix to "/Volumes/"
if input_file_path starts with smbPrefix then
set file_path to text items 2 thru -1 of splitString(input_file_path, smbPrefix) as string
set mount_name to text item 1 of splitString(file_path, "/") as string
set shell_command to "mount | grep \" on " & smbPrefix & mount_name & "\""
set mount_path to do shell script shell_command
set mount_path to text items 2 thru -1 of splitString(mount_path, "@") as string
set mount_path to text item 1 of splitString(mount_path, " on /Volumes") as string
set file_path to text items 2 thru -1 of splitString(file_path, mount_name & "/") as string
return "smb://" & mount_path & "/" & file_path
end if
return input_file_path
end getRealPath
on searchReplace(theText, SearchString, ReplaceString)
set OldDelims to AppleScript's text item delimiters
set AppleScript's text item delimiters to SearchString
set newText to text items of theText
set AppleScript's text item delimiters to ReplaceString
set newText to newText as text
set AppleScript's text item delimiters to OldDelims
return newText
end searchReplace
on toWindowsPath(file_path)
set win_path to file_path
set win_path to searchReplace(win_path, "<", "")
set win_path to searchReplace(win_path, ">.", "")
set win_path to searchReplace(win_path, ">", "")
set win_path to searchReplace(win_path, "smb://", "\\\\")
set win_path to searchReplace(win_path, "/", "\\")
return win_path
end toWindowsPath
on run {input, parameters}
set results to ""
repeat with input_file in input
set real_path to getRealPath(the POSIX path of input_file)
if real_path starts with "smb://" then
set results to results & toWindowsPath(real_path) & return
else
display dialog "ローカルパスをWindows用パスに変換できません" buttons {"OK"} default button "OK"
return ""
end if
end repeat
return results
end run
まとめ
Finderの詳細情報から見せるmacOS詳細パスはこんなに複雑だとは思いませんでした。
ただ、濁点・マウント先のパス取得・UTF-8問題といういろんな山をこえた結果、
ワンクリックでパス変換できるようなものができて嬉しかったです。
ちなみに、社内で何人かに使ってもらった結果、結構好評でした。