Get files and folders as shown in a Finder window

I wrote the following script which gets and sorts all files and folders in a folder in the exact order they are shown in a Finder window. The Finder window is set to sort by name in ascending order with folders displayed first and hidden files not shown. The following works but I wondered if there might be a simpler and faster ASObjC approach. I wrote this primarily to refine my ASObjC skills. Thanks.

use framework "Foundation"
use scripting additions

set theFolder to POSIX path of (choose folder)

getFinderList(theFolder)

on getFinderList(theFolder)
	set theFolder to current application's |NSURL|'s fileURLWithPath:theFolder
	
	set fileManager to current application's NSFileManager's defaultManager()
	set theOptions to (current application's NSDirectoryEnumerationSkipsPackageDescendants as integer) + (current application's NSDirectoryEnumerationSkipsHiddenFiles as integer)
	set enumKeys to {current application's NSURLIsDirectoryKey, current application's NSURLIsPackageKey}
	set theFiles to fileManager's contentsOfDirectoryAtURL:theFolder includingPropertiesForKeys:enumKeys options:theOptions |error|:(missing value)
	set theDescriptor to current application's NSSortDescriptor's sortDescriptorWithKey:"lastPathComponent" ascending:true selector:"localizedStandardCompare:"
	set sortedFiles to (theFiles's sortedArrayUsingDescriptors:{theDescriptor})
	
	set theFolders to current application's NSMutableArray's new()
	set theFiles to current application's NSMutableArray's new()
	repeat with anItem in sortedFiles
		set {theResult, isDirectory} to (anItem's getResourceValue:(reference) forKey:(current application's NSURLIsDirectoryKey) |error|:(missing value))
		if isDirectory as boolean then
			set {theResult, isPackage} to (anItem's getResourceValue:(reference) forKey:(current application's NSURLIsPackageKey) |error|:(missing value))
			if isPackage as boolean then
				(theFiles's addObject:anItem)
			else
				(theFolders's addObject:anItem)
			end if
		else
			(theFiles's addObject:anItem)
		end if
	end repeat
	
	set finderItemList to theFolders's arrayByAddingObjectsFromArray:theFiles
	return finderItemList as list
end getFinderList

Hi peavine.

If you know you have significantly fewer folders than files in the folder, or vice versa, a v-e-r-y slightly more efficient approach would be only to build an array of the fewer items and then “subtract” it from the full one. This may even be effective with a more even mix.

use framework "Foundation"
use scripting additions

set theFolder to POSIX path of (choose folder)

getFinderList(theFolder)

on getFinderList(theFolder)
	set theFolder to current application's |NSURL|'s fileURLWithPath:theFolder
	
	set fileManager to current application's NSFileManager's defaultManager()
	set theOptions to (current application's NSDirectoryEnumerationSkipsPackageDescendants as integer) + (current application's NSDirectoryEnumerationSkipsHiddenFiles as integer)
	set enumKeys to {current application's NSURLIsDirectoryKey, current application's NSURLIsPackageKey}
	set theFiles to (fileManager's contentsOfDirectoryAtURL:theFolder includingPropertiesForKeys:enumKeys options:theOptions |error|:(missing value))
	
	set theFiles to theFiles's mutableCopy()
	set theDescriptor to current application's NSSortDescriptor's sortDescriptorWithKey:"lastPathComponent" ascending:true selector:"localizedStandardCompare:"
	theFiles's sortUsingDescriptors:{theDescriptor}
	
	set arrangedItems to current application's NSMutableArray's new() -- Formerly theFolders.
	repeat with anItem in theFiles
		set {theResult, isDirectory} to (anItem's getResourceValue:(reference) forKey:(current application's NSURLIsDirectoryKey) |error|:(missing value))
		if isDirectory as boolean then
			set {theResult, isPackage} to (anItem's getResourceValue:(reference) forKey:(current application's NSURLIsPackageKey) |error|:(missing value))
			if not (isPackage as boolean) then (arrangedItems's addObject:anItem)
		end if
	end repeat
	
	theFiles's removeObjectsInArray:arrangedItems
	arrangedItems's addObjectsFromArray:theFiles
	
	return arrangedItems as list
end getFinderList

Thanks Nigel. Your suggestion works great but I had to put it to the test :slight_smile:

TEST FOLDER CONTAINS - PEAVINE’S SCRIPT - NIGEL’S SCRIPT

8 folders 8 files - 41 - 37 (all times are milliseconds)
4 folders 16 files - 38 - 32
2 folders 57 files - 83 - 61

To set a baseline, I tested a Finder script which returns the same results (except as aliases) on the third test folder above and the timing result was 288 milliseconds.