With Mac OS X, Apple started out in the GUI world, but over time has transitioned to a more traditional Unix world with command-line tools, but without forcing this on most users. For example, you can perform and access install information via the command-line as well as through the GUI programs Apple supplies.
The standard on Mac OS X is “the package”, and this is for atomic entities, such as applications, libraries and frameworks. Installers add packages to the system; users run them (a .app is a folder that is a package that masquerades as a file).
pkgutil command-line program gives you access to information about installed packages.
man pkgutil tells us a little bit:
pkgutil(1) BSD General Commands Manual pkgutil(1)
pkgutil -- Query and manipulate Mac OS X Installer packages and receipts.
pkgutil [options] [commands]
pkgutil reads and manipulates Mac OS X Installer flat packages, and pro-
vides access to the ``receipt'' database used by the Installer. Options
are processed first, and affect the operation of all commands. Multiple
commands are performed sequentially in the given order.
First off, you can just get a list of all the packages installed to a specific volume. For the most part, packages are installed to the root volume /, and if you don’t pass in a –volumes option, pkgutil will default to /.
brian-mac-pro:~ bfitz$ pkgutil --packages
brian-mac-pro:~ bfitz$ pkgutil --packages | wc
87 87 2549
My Mac currently has 87 packages installed on it (I don’t install a lot of things, sorry).
You can list packages that match a pattern – for example, to find all packages with the string Xcode:
brian-mac-pro:~ bfitz$ pkgutil --pkgs=.\+Xcode.\+
The trick with the regular expression is that it must cover the entire name, there’s an implied start and end anchor applied to the regex, and you need to escape characters that the shell might interpret (like <, +, \ and so on). For example, if your regex needs a backslash, then you need a backslash for that backslash.
One of the most useful commands is “I have a file on my hard disk, what installed it”. For example, something installed git to /usr/bin/git – what was it?
brian-mac-pro:~ bfitz$ pkgutil --file-info /usr/bin/git
Evidently, when I said “install command-line versions of tools” in Xcode, it installed git to the global system folder. So, what else did it install? The –files option lists all the files installed by a package, and –only-files makes it list just the files, not the directories that were created to hold those files.
brian-mac-pro:~ bfitz$ pkgutil --only-files --files com.apple.pkg.DeveloperToolsCLILeo
brian-mac-pro:~ bfitz$ pkgutil --only-files --files com.apple.pkg.DeveloperToolsCLILeo | wc
1852 1856 102002
It installed 1852 files, and the files are as expected, command line programs and man pages and even a suite of test code.
You can get more information about a package with –pkg-info.
brian-mac-pro:~ bfitz$ pkgutil --pkg-info com.apple.pkg.DeveloperToolsCLILeo
groups: com.apple.FindSystemFiles.pkg-group com.apple.DevToolsBoth.pkg-group com.apple.DevToolsNonRelocatableShared.pkg-group
brian-mac-pro:~ bfitz$ date -r 1316396966
Sun Sep 18 18:49:26 PDT 2011
The install-time flag is in Unix seconds (seconds since 1970), which I turned into a human-readable date with the date command-line tool, so you can see that I installed this package (which came from an install of Xcode) on September 18, 2011.
Here we see that com.apple.pkg.DeveloperToolsCLILeo is part of several groups, and we can discover what other packages are in a group by using –group-pkgs:
brian-mac-pro:~ bfitz$ pkgutil --group-pkgs com.apple.DevToolsBoth.pkg-group
Of course, at this point you’re reverse-engineering what some developer has as their plan for how to organize software, and you’re not likely to find this documented anywhere.