Get and sort files in a folder

It’s commonplace that I have to obtain files with a particular extension from one folder. I don’t recall where but I found the script included below. With one exception it does what I want, but I wondered if there might be any improvements:

on getFiles(sourceFolder, fileExtensions) -- sourceFolder is POSIX path and fileExtensions is list of file extensions
	set fileManager to current application's NSFileManager's defaultManager()
	set theFolder to current application's |NSURL|'s fileURLWithPath:sourceFolder
	set folderContents to fileManager's contentsOfDirectoryAtURL:theFolder includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
	set theFiles to current application's NSPredicate's predicateWithFormat_("pathExtension.lowercaseString IN %@", fileExtensions)
	set theFiles to folderContents's filteredArrayUsingPredicate:theFiles
	return theFiles as list
end getFiles

I need the returned list to be sorted by name in ascending order. I added a sort routine to the script but received an unrecognized-selector error, presumably because I cannot sort URL’s in this manner. I looked at the NSArrray and NSURL documentation but didn’t find a solution. How can I fix this or is there a better way.

on getFiles(sourceFolder, fileExtensions) -- sourceFolder is POSIX path and fileExtensions is list of file extensions
	set fileManager to current application's NSFileManager's defaultManager()
	set theFolder to current application's |NSURL|'s fileURLWithPath:sourceFolder
	set folderContents to fileManager's contentsOfDirectoryAtURL:theFolder includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
	set theFiles to current application's NSPredicate's predicateWithFormat_("pathExtension.lowercaseString IN %@", fileExtensions)
	set theFiles to folderContents's filteredArrayUsingPredicate:theFiles
	set sortedFiles to (theFiles's sortedArrayUsingSelector:"compare:") -- error "-[NSURL compare:]: unrecognized selector sent to instance 0x600001825e00" number -10000
	return sortedFiles as list
end getFiles

Thanks for the help.

NSURL instances cannot be sorted with the compare selector – as stated by the error – because NSURL doesn’t represent a single value like a string.

A solution is to use a NSSortDescriptor which sorts the array by the file name (in terms of NSURL the last path component)

on getFiles(sourceFolder, fileExtensions) -- sourceFolder is POSIX path and fileExtensions is list of file extensions
	set fileManager to current application's NSFileManager's defaultManager()
	set theFolder to current application's |NSURL|'s fileURLWithPath:sourceFolder
	set folderContents to fileManager's contentsOfDirectoryAtURL:theFolder includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
	set theFiles to current application's NSPredicate's predicateWithFormat_("pathExtension.lowercaseString IN %@", fileExtensions)
	set theFiles to folderContents's filteredArrayUsingPredicate:theFiles
	set sortDescriptors to current application's NSArray's arrayWithObject:(current application's NSSortDescriptor's sortDescriptorWithKey:"lastPathComponent" ascending:true)
	set sortedFiles to (theFiles's sortedArrayUsingDescriptors:sortDescriptors)
	return sortedFiles as list
end getFiles

Thanks Stefan. That worked great.

FWIW, I ran some timing tests on the above script and the Finder equivalent. The test folder contained 20 PDF, 20 PNG, and 20 TXT files, and I set the scripts to get PDF files only. The first-run timing results were:

ASObjC - 0.028 seconds

Finder - 1.261 seconds

The ASObjC result is with the Foundation framework in memory, which would normally be the case if ASObjC is regularly used.

Here is example of sorted files in a folder as POSIX path
This example the repeat loop start at 4 because in the folder it had 3 hidden files.

Be a ware it also count folders, so I guess other approach would consider if that matters.

use framework "Foundation"
use scripting additions

set thePath to POSIX path of (path to desktop pictures folder)
set {theResult, theError} to (current application's NSFileManager's defaultManager())'s contentsOfDirectoryAtPath:thePath |error|:(reference)
set theSort to (theResult's sortedArrayUsingSelector:"compare:") as list

set theList to {}
repeat with i from 4 to count theSort
	set theFilePath to thePath & item i of theSort
	copy theFilePath to end of theList
end repeat
return theList
use framework "Foundation"
use scripting additions

return my sortedFileListAtPath:(POSIX path of (path to desktop pictures folder))

on sortedFileListAtPath:thePath
	set {theResult, theError} to (current application's NSFileManager's defaultManager())'s contentsOfDirectoryAtPath:thePath |error|:(reference)
	set theSort to (theResult's sortedArrayUsingSelector:"compare:") as list
	set theList to {}
	repeat with i from 4 to count theSort
		set theFilePath to thePath & item i of theSort
		copy theFilePath to end of theList
	end repeat
	return theList
end sortedFileListAtPath: