指定フォルダ以下のすべてのファイルを再帰で取得するAppleScriptです。
「指定フォルダ以下のファイルを取得する」やりかたは、Spotlightを使うのがベストです。ベストではあるものの、各ユーザーのHDDなりSSDは「破損している」ケースもあって、Spotligtの検索が効かない場合もあります。
また、マウントしたLAN上のファイルサーバーに対してSpotlightが効くかどうかは実際にやってみないと分かりません。OSが異なる可能性がありますし、同じmacOSであっても効くかどうかは実際に試してみるまではっきりしません(開発時に真っ先に確認するポイントでもあります。ファイルサーバーを相手に処理するつもりかどうかの確認です)。
そこで、地道に再帰処理でファイルを取得すること「も」試してみることになるわけですが、ここでFinderを使うと遅くなります。
OS X 10.6以降の64ビット化されたいわゆる「Cocoa Finder」は処理速度が低下しているため、大量のファイル処理をFinder経由で行うことは「悪手」といえます。数百個ぐらいでけっこうな処理速度の低下がみられます。1,000を超えると露骨に速度が下がります。フィルタ参照で条件をつけて抽出するのも速度低下につながります。さらに複数のフィルタ条件を指定するとアホみたいに遅くなります。Cocoa Finderの性能低下はハンパではありません。
たまに、Classic Mac OSの環境しか知らない人が久しぶりに現代の(64ビット化された)macOS上で昔と同じようにFinderに対して膨大なファイルの処理を行わせて「遅い」と文句を言っているのを見かけますが、Finder経由でのファイル処理が現実的ではないという状況を知らなければそういう感想になってしまうかもしれません。
# Classic MacOS〜macOS 10.6ぐらいまではFinder経由で行っても、極端に時間がかかることはありませんでした。それ以降の環境のお話です。また、macOS 10.7以降でも、数個〜数十程度のすくないファイルを処理する場合には、あまり問題になりません
そこで、NSFileManagerを用いてファイル処理を行うことで、「Spotlightほど速くはないものの、Finderで処理するよりははるかに高速」な処理を行えます。
AppleScript名:指定フォルダ以下のすべてのファイルを再帰で取得 v2 |
— Created 2017-08-04 by Takaaki Naganoya — 2017 Piyomaru Software use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" property NSString : a reference to current application’s NSString property NSPredicate : a reference to current application’s NSPredicate property NSFileManager : a reference to current application’s NSFileManager property NSMutableArray : a reference to current application’s NSMutableArray –set aFol to POSIX path of (choose folder) set aFol to POSIX path of (path to desktop folder) –set aList to retFullPathWithinAFolderWithRecursive(aFol) of me set bList to retFullPathWithinAFolderWithRecursiveFilterByExt(aFol, "scpt") of me –set cList to retFilenameWithinAFolderWithRecursiveFilterByExt(aFol, {"scpt", "scptd"}) of me –set dList to retFullPathWithinAFolderWithRecursiveFilterByExtAndFileNameString(aFol, "png", "スクリーン") of me –set eList to retFullPathWithinAFolderWithRecursiveFilterByExtAndFileNameString(aFol, {"scpt", "scptd"}, "並列") of me –指定フォルダ以下のすべてのファイルを再帰で取得 on retFilenamesWithinAFolderWithRecursive(aFol) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:(aFullPath’s lastPathComponent()’s stringByDeletingPathExtension() as string) end repeat return anArray as list end retFilenamesWithinAFolderWithRecursive –指定フォルダ以下のすべてのファイルを再帰で取得 on retFullPathWithinAFolderWithRecursive(aFol) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:(aFullPath’s lastPathComponent()’s stringByDeletingPathExtension() as string) end repeat return anArray as list end retFullPathWithinAFolderWithRecursive –指定フォルダ以下のすべてのファイルを再帰で取得(拡張子で絞り込み) on retFilenameWithinAFolderWithRecursiveFilterByExt(aFol, aExt) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:aFullPath end repeat set thePred to NSPredicate’s predicateWithFormat:"pathExtension == [c]%@" argumentArray:{aExt} set bArray to anArray’s filteredArrayUsingPredicate:thePred return bArray as list end retFilenameWithinAFolderWithRecursiveFilterByExt –指定フォルダ以下のすべてのファイルを再帰で取得(拡張子で絞り込み) on retFullPathWithinAFolderWithRecursiveFilterByExt(aFol, aExt) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:aFullPath end repeat set thePred to NSPredicate’s predicateWithFormat:"pathExtension == [c]%@" argumentArray:{aExt} set bArray to anArray’s filteredArrayUsingPredicate:thePred return bArray as list end retFullPathWithinAFolderWithRecursiveFilterByExt –指定フォルダ以下のすべてのファイルを再帰で取得(拡張子リストで絞り込み) on retFullPathWithinAFolderWithRecursiveFilterByExtList(aFol, aExtList) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:aFullPath end repeat set thePred to NSPredicate’s predicateWithFormat:"pathExtension IN [c]%@" argumentArray:{aExtList} set bArray to anArray’s filteredArrayUsingPredicate:thePred return bArray as list end retFullPathWithinAFolderWithRecursiveFilterByExtList –指定フォルダ以下のすべてのファイルを再帰で取得(文字列と拡張子で絞り込み) on retFullPathWithinAFolderWithRecursiveFilterByExtListAndFileNameString(aFol, aExt, aNameString) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:aFullPath end repeat set thePred to NSPredicate’s predicateWithFormat:"pathExtension == [c]%@ && lastPathComponent CONTAINS %@" argumentArray:{aExt, aNameString} set bArray to anArray’s filteredArrayUsingPredicate:thePred return bArray as list end retFullPathWithinAFolderWithRecursiveFilterByExtListAndFileNameString –指定フォルダ以下のすべてのファイルを再帰で取得(文字列と拡張子リストで絞り込み) on retFullPathWithinAFolderWithRecursiveFilterByExtAndFileNameString(aFol, aExtList, aNameString) set anArray to NSMutableArray’s array() set aPath to NSString’s stringWithString:aFol set dirEnum to NSFileManager’s defaultManager()’s enumeratorAtPath:aPath repeat set aName to (dirEnum’s nextObject()) if aName = missing value then exit repeat set aFullPath to aPath’s stringByAppendingPathComponent:aName anArray’s addObject:aFullPath end repeat set thePred to NSPredicate’s predicateWithFormat:"pathExtension IN [c]%@ && lastPathComponent CONTAINS %@" argumentArray:{aExtList, aNameString} set bArray to anArray’s filteredArrayUsingPredicate:thePred return bArray as list end retFullPathWithinAFolderWithRecursiveFilterByExtAndFileNameString |