You can use Metadata Query. The advantage is that you can pass several folders at a time.
use AppleScript version "2.5"
use framework "Foundation"
use framework "AppKit"
use scripting additions
set theTargets to {"/Users/me/Desktop/"}
set theQuery to current application's NSMetadataQuery's new()
theQuery's setPredicate:(current application's NSPredicate's predicateWithFormat:"kMDItemContentType == 'com.apple.alias-file' OR kMDItemContentType == 'com.apple.alias-record'")
theQuery's setSearchScopes:theTargets
theQuery's startQuery()
repeat while theQuery's isGathering() as boolean
delay 0.01
end repeat
theQuery's stopQuery()
set theCount to theQuery's resultCount()
set theResults to current application's NSMutableArray's array()
repeat with iQuery from 0 to (theCount - 1)
set thePath to ((theQuery's resultAtIndex:iQuery)'s valueForAttribute:(current application's NSMetadataItemPathKey))
set theURL to (current application's NSURL's fileURLWithPath:thePath)
(theResults's addObject:theURL)
end repeat
return (theResults's valueForKey:"path") as list -- if you want POSIX paths
return (theResults) as list -- if ou want HFS files
I’m wanting to avoid Spotlight in this case, but I wasn’t thinking about searching via UTI – so your response get’s me on the right track for this project. (I think…)
Nevertheless – I’ll use the Metadata Query for other things.
use AppleScript version "2.5"
use framework "Foundation"
use framework "AppKit"
use scripting additions
-- get the folder URL
set theFolderURL to current application's NSURL's fileURLWithPath:"/Users/me/Desktop/"
-- get URL of all items in folder, recursively
set keysToRequest to {"NSURLTypeIdentifierKey"}
set theFileManager to current application's NSFileManager's defaultManager()
set allURLs to (theFileManager's enumeratorAtURL:theFolderURL includingPropertiesForKeys:keysToRequest options:6 errorHandler:(missing value))'s allObjects()
-- build the predicate
set thePredicate to (current application's NSPredicate's predicateWithFormat:"NSURLTypeIdentifierKey UTI-CONFORMS-TO 'com.apple.resolvable'") -- This will return all kind of links (including Symbolic links).
-- build an array with URLs satisfying the predicate
set filteredArray to current application's NSMutableArray's new()
repeat with oneURL in allURLs
set keyValue to (oneURL's resourceValuesForKeys:keysToRequest |error|:(missing value))
if ((thePredicate's evaluateWithObject:keyValue) as boolean) then (filteredArray's addObject:oneURL) -- This works even if keyValue is missing value.
end repeat
-- convert URL array to file list
return filteredArray as list
If you’re only interested in alias files, this is more direct and slightly faster — and possibly what you were trying to avoid in the first place :
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
-- get the folder URL
set theFolderURL to current application's NSURL's fileURLWithPath:"/Users/me/Desktop/"
-- get URL of all items in folder, recursively
set isAliasKey to current application's NSURLIsAliasFileKey
set theFileManager to current application's NSFileManager's defaultManager()
set allURLs to (theFileManager's enumeratorAtURL:theFolderURL includingPropertiesForKeys:{isAliasKey} options:((current application's NSDirectoryEnumerationSkipsPackageDescendants) + ((current application's NSDirectoryEnumerationSkipsHiddenFiles) as integer)) errorHandler:(missing value))'s allObjects()
-- build an array with URLs to alias files
set filteredArray to current application's NSMutableArray's new()
repeat with oneURL in allURLs
set keyValue to end of (oneURL's getResourceValue:(reference) forKey:isAliasKey |error|:(missing value))
if (keyValue as boolean) then (filteredArray's addObject:oneURL)
end repeat
-- convert URL array to file list
return filteredArray as list
current application's NSURL's URLByResolvingAliasFileAtURL:oneURL options:0 |error|:(missing value)
--> NSURL or missing value
The Xcode documentation doesn’t say what the possible options: are. It only tells of one which isn’t supported. This turns out to be one of three NSURLBookmarkResolutionOptions, the only one which may be of interest here being current application's NSURLBookmarkResolutionWithoutMounting.
Your quote’s actually from the script @ionah gave you.
There’s also:
set allURLs to theFileManager's contentsOfDirectoryAtURL:theFolderURL includingPropertiesForKeys:{isAliasKey} ¬
options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) ¬
|error|:(missing value)
It’s simpler; but I haven’t compared it with the enumerator method for speed and I imagine the choice of which to use would depend on the overall purpose of the script.
Hmm. I can’t comment about symbolic lilnks — except that when I try the script on my own Applications folder, two of the four hits aren’t actually in the heirarchy. Could this be something to do with symbolic links?
What frameworks I’ve found so far on my Mojave machine are ordinary folders in the Finder too. None of them are (visible) in the Applications folder.
All of the frameworks in the Frameworks folders of my System, Local, and User Library folders appear with those icons, have disclosure triangles (or whatever they’re called) beside them in Finder list views, and can be double-clicked open like regular folders. There are also a few aliases or links (which may or may not have those icons) to frameworks elsewhere.
Your script and mine return exactly the same results for my Applications folder (including the two hits from outside the hierarchy), my three Frameworks folders, and my three Scripting Additions folders. (Although my third-party OSAXen don’t work in Mojave, they’re still there. None of the Scripting Additions folders produce any hits.)
Just in case the three of us are talking at cross-purposes, I’m referring to ionah’s script and mine, which simply find alias files. I’m not talking about any later adaptation which attempts to follow the alias links.
Yep.
But to avoid the script searching in unwanted containers, I thought about this:
set {isAlias, isRegular} to {NSURLIsAliasFileKey, NSURLIsRegularFileKey} of (oneURL's resourceValuesForKeys:{"NSURLIsAliasFileKey", "NSURLIsRegularFileKey"} |error|:(missing value))
if (isAlias as boolean) and (isRegular as boolean) then (filteredArray's addObject:oneURL)
What’s your opinion?
And what do you think about using Metadata Query for this task?