2020-02-26T14:20:39+09:00

AppleScript でフォルダの中身一覧を取得する方法の速度比較

contents

伝統的には、AppleScript でフォルダの中身一覧を取得するコマンドとして、スクリプティング機能追加 StandardAdditoins.osax が提供してる lis folder というコマンドがあります。でも用語辞書には

This command is deprecated; use ‘tell application "System Events" to get the name of every item of folder …’.

とあります。じゃあ、System Events に大人しく乗り換えるかと、ちょっと躊躇します。遅くなるのが予想できますから。

System Events を使う以外にも、OS X 10.10 からなら AppleScriptObjC で Cocoa の NSFileManager も使えます。

はたして、どの方法が一番速いのか、拙作の AppleScript ライブラリ LapTime を使って、比べてみました。

結論から言えば、NSFileManager が一番速い。スクリプティング機能追加のコマンド list folder より倍ぐらい速い。そもそも大した差じゃないかもしれないけど、有意な差があります。

漠然とAppleScriptObjC は AppleScript と Objective C の間の変換のオーバヘッドが大きそうと思っていました。Objective C のメソッドの呼び出しを何回もしないといけないし。しかし、スクリプティング機能追加コマンドより速いようです。理由はよくわかりません。list folder コマンドの実装が良くないということかしら?

一番遅いのは、アプリケーション System Events に AppleEvent を送った場合です。一般に、AppleScript のボトルネックになるのがアプリケーションとの通信です。AppleScript はアプリケーションと通信するのが主任務ですが、それを避けられるなら避けた方が実行速度が上がります。本末転倒にならない程度に。

結論として、AppleScriptObjC で Cocoa を呼び出しましょう、ということになりますが、Cocoa はメソッドが冗長なのが玉に瑕。そこで、Cocoa を使ったよく使う処理をライブラリとしてまとめると、幸せになれるんじゃないでしょうか。拙作 XFile では NSFileManager を使ったファイル処理をまとめてあります。

use scripting additions
use LapTime : script "LapTime"
use framework "AppKit"
property NSFileManager : class "NSFileManager"

set a_path to "/usr/bin"
set tm to LapTime's start_timer()

(* Cocoa *)
tell NSFileManager's defaultManager()
(its contentsOfDirectoryAtPath:a_path |error|:(missing value)) as list
end tell
tm's lap:"NSFileManager"

(* Scripting Addition *)
list folder a_path
tm's lap:"StandardAdditions"

(* System Events *)
tell application "System Events"
name of every item of folder a_path
end tell
tm's lap:"System Events"

tm's lap_times()

(*[Lap Times]
NSFileManager 5.064010620117 [ms]
StandardAdditions 13.827919960022 [ms]
System Events 29.550075531006 [ms]*)