Reputation: 6247
I'd like to be able to determine if a directory such as a '.app' is considered to be a package or bundle from Finder's point of view on the command line. I don't think this would be difficult to do with a small shell program, but I'd rather not re-invent the wheel if I don't have to.
Upvotes: 6
Views: 11668
Reputation: 133189
On all systems with Spotlight, using mdls
you can detect bundles looking at the kMDItemContentTypeTree property. E.g.:
mdls -name kMDItemContentTypeTree "/Applications/Safari.app"
produces the following output for me
kMDItemContentTypeTree = (
"com.apple.application-bundle",
"com.apple.application",
"public.executable",
"com.apple.localizable-name-bundle",
"com.apple.bundle",
"public.directory",
"public.item",
"com.apple.package"
)
Whenever you see com.apple.package
there, it is supposed to be displayed as a package by Finder. Of course, everything with "bundle" in the name implies that already but not all packages are bundles (bundles are a specific subset of packages that have a well defined directory structure).
You can get a list of all registered file type extensions, using this command (OS X prior to Leopard):
/System/Library/Frameworks/ApplicationServices.framework/Frameworks\
/LaunchServices.framework/Support/lsregister -dump
or for Leopard and later:
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks\
/LaunchServices.framework/Versions/A/Support/lsregister -dump
Every file extension there has flags. If the package flag is set, this is a package.
E.g.
claim id: 806354944
name: Bundle
role: none
flags: apple-internal relative-icon-path package
icon: Contents/Resources/KEXT.icns
bindings: .bundle
--------------------------------------------------------
claim id: 1276116992
name: Plug-in
role: none
flags: apple-internal relative-icon-path package
icon: Contents/Resources/KEXT.icns
bindings: .plugin
Compare this to a file that is no bundle
claim id: 2484731904
name: TEXT
role: viewer
flags: apple-internal
icon:
bindings: .txt, .text, 'TEXT'
The only way to really get all bundles is by looking up in the LaunchService database (the one we dumped above). If you just go by whether it has a plist or not or whether the bundle bit is set or not, you might catch some or even many bundles, but you can't catch all of them. This is the database Finder uses to determine
and some more stuff.
[EDIT: Added path for Leopard, thanks to Hagelin for the update]
Upvotes: 4
Reputation: 101
This is a bit late, but: it seems you can detect bundles using the mdls command. Specifically, the (multi-line) output of:
mdls -name kMDItemContentTypeTree /Path/To/Directory
Will contain the string
"com.apple.package"
(including the quotation marks, at least as of Lion) somewhere if the directory is a package. If the package is also a bundle, the output will also contain
"com.apple.bundle"
and, last but not least, if it is specifically an application bundle, the output will also contain
"com.apple.application-bundle"
(That's according to some very limited testing, but from what Apple's documentation on Uniform Type Identifiers, and the man page for mdls, this should hold true. And for the items I tested, this was true for non-Apple-provided bundles as well, which is what you would expect given the purpose of UTIs.)
Upvotes: 10
Reputation: 16678
While you can identify some bundles based on the existence of './contents/Info.plist", it isn't required for all bundle types (e.g. documents and legacy bundles). Finder also identifies a directory as a bundle based on file extension (.app, .bundle, etc) or if the bundle bit is set.
To check the bundle bit from the command line use:
getFileInfo -aB directory_name
In order to catch all cases I would check:
Upvotes: 4
Reputation: 44331
<plug>
My launch tool has a feature for this. For example:
% launch -f Guards.oo3
Guards.oo3: non-application package
type: '' creator: ''
kind: OmniOutliner 3
content type ID: com.omnigroup.omnioutliner.oo3-package
contents: 1 item
created: 3/6/09 3:36:50 PM
modified: 3/6/09 4:06:13 PM
accessed: 4/12/09 1:10:36 PM [only updated by Mac OS X]
backed up: 12/31/03 6:00:00 PM
% launch -f /Applications/Safari.app
/Applications/Safari.app: scriptable Mac OS X application package
type: 'APPL' creator: 'sfri'
architecture: PowerPC 7400, Intel 80x86
bundle ID: com.apple.Safari
version: 4 Public Beta
kind: Application
content type ID: com.apple.application-bundle
contents: 1 item
created: 8/21/07 5:11:33 PM
modified: 2/24/09 7:29:51 PM
accessed: 4/12/09 1:10:51 PM [only updated by Mac OS X]
backed up: 12/31/03 6:00:00 PM
You should be able to get what you want by checking to see if the first line of output ends in 'package'.
launch
is in Fink and MacPorts too.
</plug>
Upvotes: 1
Reputation:
There ought to be a way to do it easily from the command line, because as an AppleScript user, I can do it using System Events. So if all else fails, you can execute the necessary AppleScript from the command line as follows:
$ FILE=/Users/myuser/Desktop/foo.rtfd
$ osascript -e "tell application \"System Events\" to get package folder of alias POSIX file \"${FILE}\""
result is
true
Upvotes: 0
Reputation: 48458
A bundle should always have a file `./contents/Info.plist'. You can check for the existance of this in a directory, if so then it's a package/bundle.
Upvotes: -2