Fun with pkgutil

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).

The 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
volume: /
path: /usr/bin/git

install-time: 1316396966
uid: 0
gid: 0
mode: 755
brian-mac-pro:~ bfitz$

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
brian-mac-pro:~ bfitz$ pkgutil --only-files  --files | 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
volume: /
location: /
install-time: 1316396966
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 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

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>