Macos 确定目录是Mac OS X终端中的捆绑包还是包?

Macos 确定目录是Mac OS X终端中的捆绑包还是包?,macos,terminal,Macos,Terminal,我希望能够从Finder在命令行上的角度确定诸如“.app”之类的目录是否被视为包或捆绑包。我认为用一个小的shell程序实现这一点并不困难,但如果不需要的话,我不想重新发明轮子。一个包应该始终有一个文件“./contents/Info.plist”。您可以在目录中检查是否存在此文件包,如果存在,则它是一个包/捆绑包。虽然您可以根据“./contents/Info.plist”的存在来识别某些捆绑包,但并非所有捆绑包类型(例如文档和旧捆绑包)都需要此文件包。Finder还根据文件扩展名(.app

我希望能够从Finder在命令行上的角度确定诸如“.app”之类的目录是否被视为包或捆绑包。我认为用一个小的shell程序实现这一点并不困难,但如果不需要的话,我不想重新发明轮子。

一个包应该始终有一个文件“./contents/Info.plist”。您可以在目录中检查是否存在此文件包,如果存在,则它是一个包/捆绑包。

虽然您可以根据“./contents/Info.plist”的存在来识别某些捆绑包,但并非所有捆绑包类型(例如文档和旧捆绑包)都需要此文件包。Finder还根据文件扩展名(.app、.bundle等)将目录识别为捆绑包或者如果设置了bundle位

要从命令行检查bundle位,请使用:

getFileInfo -aB directory_name
为了抓住所有案例,我将检查:

  • 包位设置好了吗
  • 如果没有,它是否具有将其标识为捆绑包的文件扩展名?(请参阅)
  • 如果不是,它可能不是一个捆绑包
更新: 在所有具有Spotlight的系统上,使用
mdls
可以检测查看kMDItemContentTypeTree属性的捆绑包。例如:

mdls -name kMDItemContentTypeTree "/Applications/Safari.app"
为我生成以下输出

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"
)
无论何时在那里看到
com.apple.package
,它都应该由Finder显示为一个包。当然,名称中带有“bundle”的所有内容都意味着已经但并非所有包都是包(bundle是具有定义良好的目录结构的包的特定子集)


旧答案: 您可以使用以下命令获得所有已注册文件类型扩展名的列表(Leopard之前的OS X):

或Leopard及更高版本:

/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks\
/LaunchServices.framework/Versions/A/Support/lsregister -dump
每个文件扩展名都有标志。如果设置了包标志,则这是一个包

例如

将此文件与没有捆绑包的文件进行比较

    claim   id:            2484731904
            name:          TEXT
            role:          viewer
            flags:         apple-internal  
            icon:          
            bindings:      .txt, .text, 'TEXT'
真正获取所有捆绑包的唯一方法是查找LaunchService数据库(我们上面转储的数据库)。如果只查看它是否有plist或捆绑包位是否已设置,您可能会捕获一些甚至多个捆绑包,但无法捕获所有捆绑包。这是数据库查找器用来确定的

  • 这个目录是不是一个包
  • 这是否是已知的文件扩展名
  • 对于此文件类型,哪些应用程序应列在“打开方式”下
  • 我应该使用哪个图标来显示此文件类型
还有更多的东西


[编辑:为Leopard添加了路径,感谢Hagelin的更新]

应该有一种从命令行轻松完成的方法,因为作为AppleScript用户,我可以使用系统事件来完成。因此,如果所有其他操作都失败,您可以从命令行执行必要的AppleScript,如下所示:

$ FILE=/Users/myuser/Desktop/foo.rtfd
$ osascript -e "tell application \"System Events\" to get package folder of alias POSIX file \"${FILE}\""
结果是

true

我的工具具有此功能。例如:

% 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
您应该能够通过检查第一行输出是否以“package”结尾来获得所需的内容

launch
也在Fink和MacPorts中


这有点晚了,但是:您似乎可以使用mdls命令检测捆绑包。具体而言,以下命令的(多行)输出:

mdls -name kMDItemContentTypeTree /Path/To/Directory
将包含字符串

"com.apple.package"
(包括引号,至少在Lion中是这样)如果目录是一个包的话。如果包也是一个包,那么输出也将包含

"com.apple.bundle"
"com.apple.application-bundle"
最后但并非最不重要的一点是,如果它是一个特定的应用程序包,那么输出也将包含

"com.apple.bundle"
"com.apple.application-bundle"

(这是根据一些非常有限的测试得出的,但从苹果公司关于统一类型标识符的文档和MDL的手册页来看,这应该是正确的。对于我测试的项目,非苹果公司提供的捆绑包也是正确的,考虑到UTIs的用途,这是您所期望的。)

应用程序总是有一个contents/Info.plist,但这不是包/捆绑包的要求。大多数文档捆绑包都没有这种结构。这是正确的。我的研究表明,对于文档捆绑包之类的东西,Finder依赖于“扩展”“在目录名中使用。这是不真实的,不是每个bundle都有一个plistIn Leopard命令是“/System/Library/Frameworks/CoreServices.framework/Versions/a/Frameworks/LaunchServices.framework/Versions/a/Support/lsregister-dump”我想澄清一下。从下面的答案可以看出,文件系统中实际上没有为bundle目录设置“bundle位”,只有Finder知道根据逻辑和启发式以及特定“文件扩展名”的注册将它们显示为文件。这是真的吗?我一直在到处寻找如何在“unix”端确定目录是否是一个捆绑包(以编程方式,Obj-C)——给定一个文件/目录的“stat”结构没有用。真相在哪里?