Searching for Alias Files (Recursively – Not Descending into Packages)

Sorry, I haven’t really been following. The decisions in terms of resource keys can be a bit arbitrary: they’re defined how they’re defined.

Metadata queries are super-fast, but they rely on the indexing being up to date (and in the case of non-startup disks, the disks being indexable). These days that seems to be less of an issue than in the past, but unless the speed difference is very large, and/or it massively simplifies things, I much prefer the comfort of one less thing to worry about.

1 Like

On my machine, both scripts do search in the content of frameworks. So the difference may be between Sierra and Mojave, or there may be something particular about your Microsoft 2011 frameworks.

@NigelGarvey
This seems to be a Sierra issue: I have the same problem with the /System/Library/Frameworks folder.

@ShaneStanley
Thanks for the enlightenments!

Hey @ionah,

When I do stuff for myself I don’t mind using Spotlight (usually), because I’ll have a pretty good idea if it’s failing on something.

On my system I’ve seen items regularly fail to get indexed, although it’s not usually a big problem for me.

When I’m building something for friends/clients I prefer more bomb-proof methods, so their task gets done without issue – and I don’t have to provide tech-support…

Hopefully when I finally get my new computer and move up from Sierra, I’ll have fewer indexing issues – but that remains to be seen.

-Chris

Hey Guys,

I really appreciate all of your input on this.  :smile:

-Chris

For some reason — hopefully not age related :grimacing: — I wrote in three places above of having a High Sierra system. It is in fact Mojave. Apologies to anyone adversely affected. I’ve now corrected my posts.

Hey Nigel,

Your code in post #5 would seem to resolve symlinks.

Is that the expected behavior?

-Chris

Hi Chris.

No it’s not. But something odd’s happening, as I noted in post #12 when I mentioned that a couple of my results for the Applications folder are outside that hierarchy. :confused:

The Discussion of enumeratorAtURL:includingPropertiesForKeys:options:errorHandler: in the Xcode documentation explicitly states: “The method does not traverse symbolic links or mount points encountered in the enumeration process.”

NSURL has a method URLByResolvingSymlinksInPath, which suggests that not using that method doesn’t resolve symbolic links if NSURLs happen to point to them.

There are separate NSURLResourceKeys for NSURLIsSymbolicLinkKey and NSURLIsAliasFileKey.

Aha! My “outside the hierarchy” results seem to be happening at the coercion-to-list stage right at the end. If I leave off the as list, all four NSURL results are in the Applications folder. This suggests it’s the scripting bridge rather than any of the script’s methods that’s resolving the aliases — some of them, anyway.

1 Like

Or simply AppleScript itself. Try this:

set x to "/Users/shane/Desktop/AAAAAA/Untitled.jpg" -- this is a symlink
x as «class furl» -- returns furl for linked file
1 Like

Hey Nigel and Shane,

Okay, we can get a path list from the array easily enough:

set filePathList to (filteredArray's valueForKey:"path") as list

And this produces the true path to the symlink itself.

But as soon as we try to coerce it to something… Poof! It points to the linked file.

repeat with thePath in filePathList
   set (contents of thePath) to alias (POSIX file (contents of thePath))
end repeat

I don’t normally use symlinks, but this is potentially a sizable pitfall.

What’s the best way to detect and filter-out symlinks?

-Chris

Well. Taking heed of what Shane said in post #18

… this checks both keys. It only returns one item for my Applications folder instead of the previous four. I was expecting it to return two, as only two of the four were being “resolved”. I’ll look into this.

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:"/Applications/"

-- get URL of all items in folder, recursively
set isAliasKey to current application's NSURLIsAliasFileKey
set isSymlinkKey to current application's NSURLIsSymbolicLinkKey
set aliasNSymlinkKeys to current application's NSArray's arrayWithArray:({isAliasKey, isSymlinkKey})
set theFileManager to current application's NSFileManager's defaultManager()
set allURLs to (theFileManager's enumeratorAtURL:theFolderURL includingPropertiesForKeys:(aliasNSymlinkKeys) 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()
set isAliasButNotSymlink to (current application's class "NSDictionary"'s dictionaryWithObjects:({true, false}) forKeys:(aliasNSymlinkKeys)) as record

repeat with oneURL in allURLs
	set keyValues to (oneURL's resourceValuesForKeys:(aliasNSymlinkKeys) |error|:(missing value)) as record
	if (keyValues is equal to isAliasButNotSymlink) then (filteredArray's addObject:oneURL)
end repeat

-- convert URL array to file list
return filteredArray as list