Does anybody know a way to get a list of all the applications installed on a Harddisk or getting a list from every application that has a certain creator?
All my scripts will only find the first application it can find or I have to specify the direct folder where the applications recide, to get multiple applications
What I need or want is a more global function for it.
use AppleScript version "2.5"
use framework "Foundation"
use script "FileManagerLib" version "2.2.1"
use scripting additions
set theRootFolderPosixPath to POSIX path of (path to startup disk)
set folderContents to objects of theRootFolderPosixPath ¬
searching subfolders true ¬
include invisible items false ¬
include folders true ¬
include files true ¬
result type urls array
set thePred to current application's NSPredicate's predicateWithFormat:"pathExtension IN[c] %@" argumentArray:{{"app"}}
set all_Applicatiions_List to (folderContents's filteredArrayUsingPredicate:thePred) as list
I don’t know yet how to filter the files in AppleScriptObjc with UTI. Can get AppleScriptObjc UTI of the files without applying repeat loop?
The following code throws the error “Unable to parse the format string "UTI-CONFORMS-TO %@"” number -10000:
set thePred to current application's NSPredicate's predicateWithFormat:"UTI-CONFORMS-TO %@" argumentArray:{{"public.image"}}
set all_Applicatiions_List to (folderContents's filteredArrayUsingPredicate:thePred) as list
That’s going to take a while, though – getting every file on the disk is a big ask. Hmm, I just did a test and it’s not as bad as I feared, taking just over a minute here (plus a while to present the result).
Anyway, if Casper is happy enough to rely on Spotlight indexing, this does it in less than a second on my Mac:
use AppleScript version "2.5" -- macOS 10.11 or later
use scripting additions
use script "Metadata Lib" version "2.0.2"
set theFolder to POSIX path of (path to startup disk)
set thePaths to perform search in folders {theFolder} predicate string "kMDItemFSName ENDSWITH[c] '.app'"
Either way, Casper will need to download and instal the relevant script library from here:
As this script relies on Spotlight indexing, as does mdfind, would this be expected to produce the same output as:
do shell script "mdfind 'kMDItemFSName == \"*.app\"'"
I’m not a massive fan of calling out to a shell from within an AppleScript, and would probably prefer to enumerate specific directories known to contain applications, but can’t deny that the return speed from the pre-indexed search is astounding.
To the OP: purely out of curiosity, what necessitates having to perform an exhaustive systemwide search for app bundles ? A lot of them living outside of the regular spots seem to be those residing inside other bundles, and wouldn’t seem to be of much concern —to me at least—in an immediately obvious way. I have my system maintain a text file containing a list of applications located inside /Applications and /System/Library/CoreServices, which are enumerated by a script semi-regularly to keep the file up-to-date. What sort of project are you working on ?
I believe the right-hand-side of the predicate string needs to evaluate to a unary string value in order to have each array element make a comparison against it. Your argument array contains a single-item list with a UTI string, which I’m imagining would lead to a non-sensical comparison by each array element against an array object, which would never return true if it got that far. See if it works or if your error message changes when you remove the UTI string from its list, i.e.
If you wanted to have comparisons made against multiple UTI strings, you might be able to do so using ANY, possibly like this:
predicateWithFormat:"UTI-CONFORMS-TO ANY %@" argumentArray:{{"public.image", "public.text", "public.data", ... }}
That said, I haven’t tested any of this so I may be wrong, or if I’m at least in the ball park, either Shane can correct me, or you can tweak it a bit more from there.
Yes (I didn’t check exactly, but the totals match here). There are two different APIs to do a metadata search, one C-based and one using Objective-C. The latter uses typical NSPredicate syntax, so there can be subtle differences in the predicate string. mdls presumably uses the C-based API, which was released before the Objective-C one.
I could have used “kMDItemFSName LIKE ‘*.app’”. I suppose I used ENDSWITH because my gut feeling is that avoiding wildcards is always going to be quicker, but it’s probably more superstition/hope, and irrelevant here.
Either way, both APIs presumably call exactly the same code.
I'm not a massive fan of calling out to a shell from within an AppleScript
For a moment I missed the not in there, and was about to mount an argument
No. The UTI of a file is not a property, but a resource property. You can only avoid loops with properties (that is, where you can use methods that require no arguments).
And if it were a property, UTI-CONFORMS-TO is an operator, like CONTAINS or ENDSWITH, so the predicate would need to be of the form “ UTI-CONFORMS-TO %@”.
For a Spotlight search, you can use this:
set thePaths to perform search in folders {theFolder} predicate string "kMDItemContentTypeTree CONTAINS %@" search arguments {"public.image"}
You’re mostly right about the right-hand-side, although ANY is for use on the left-hand-side – you would probably need to use ORs to check on multiple UTIs. There’s just the small matter of having a left-hand-side
The lib return the aliases and the symbolic links which Spotlight doesn’t.
Here the lib return also Darktable.app and GIMP-2.10.app which Spotlight doesn’t.
I may understand for the aliases and symbolic links, not for the two named applications.
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 6 aout 2019 10:17:08
Some of it could be. Many of them were within the Xcode bundle, though, and I can understand that not being indexed. I didn’t investigate any further than that.
for GIMP:
gegl public.unix-executable
gimp public.unix-executable
gimp-bin public.unix-executable
gimp-console dyn.ah62d4rv4ge8xcqa - a 17 bytes long alias pointing to gimp-console-2.10 (below)
gimp-console-2.10 dyn.ah62d4rv4ge8xcqa
gimp-debug-tool dyn.ah62d4rv4ge8xcqa - a 6 bytes long alias pointing to gimp-debug-tool-2.0 (below)
gimp-debug-tool-2.0 dyn.ah62d4rv4ge8xcqa
gimptool-2.0 dyn.ah62d4rv4ge8xa
python public.unix-executable
python2 public.unix-executable - a 6 bytes long alias pointing to python (above)
xdg-email public.unix-executable
Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 6 aout 2019 16:18:15
I don’t know, to be honest. I downloaded Darktable, and couldn’t see anything problematic. But there’s nothing wrong with having multiple executables in Contents/MacOS – in fact, I’ve seen one Apple employee encouraging it only recently. It’s a bit of a mystery.