还原文件类型关联


12

我有时会使用iTunes Music Store软件包。这些软件包具有.itmsp扩展名。像.app.itmsp本质上是一个容器目录。.itmsp文件夹包含XML和媒体文件。

最新的Xcode和/或Mac OS X更新(在Mac OS 10.8.3上为Xcode 4.6.1)已劫持了具有.itmsp扩展名的目录的文件类型关联。以前,它们被视为普通文件夹-无需双击即可查看内部。现在,我必须双击它们才能与它们交互。当我这样做时,一个名为Application Loader的程序将尝试打开它们。为了看到里面,我必须右键单击并选择“显示包装内容”。我随时都在处理成千上万个这样的文件,因此无法正常工作。

我尝试使用Get Info和RCDefaultApp更改或删除文件类型关联。都不行。删除文件类型关联只会将.itmsp目录变成空白文件。完全删除Application Loader.app也是如此。无论哪种情况,如果没有右键单击,我仍然无法浏览内容。

先前接受的答案已有一段时间了:lsregister -u /Applications/Contents/Applications/Application\ Loader.app/自从我更新Xcode和/或Mac OS X以来,它已经停止工作。如果您安装了Xcode,则应该可以通过命名目录来进行测试foo.itmsp

如何使.itmsp文件再次被视为文件夹?


您是否尝试过将文件拖放到Xcode App Icon上,看看它是否满足您的要求?
MrDaniel

谢谢你的建议。它与手头的问题无关,因此,我将尝试编辑我的问题以阐明我的意图。
michaelmichael

1
您正在运行什么版本的OS X?什么版本的Xcode?
Old Pro

我删除了我的Answer,它从CFBundleDocumentTypes中删除了类型,并杀死了Launch Service数据库。它可以工作一段时间,但稍后似乎又可以重新声明其自身。
markhunte

Answers:


11

问题:.itmsp文件夹显示为文件

Finder将.itmsp文件夹视为,即就像它们是单个文件一样。例如,在列视图中,.itmsp文件夹中包含的所有内容都是不可见的,仅显示文档图标:

在此处输入图片说明

如果满足以下任一条件,则Finder会将目录视为一个包(来自Bundle编程指南):

  1. 该目录具有已知的文件扩展名:.app,.bundle,.framework,.plugin,.kext等(如。中的定义/System/Library/CoreServices/CoreTypes.bundle/Contents/Info.plist。这是一个二进制plist,使用Xcode:打开open -a Xcode Info.plist)。

  2. 该目录具有一个扩展,其他一些应用程序则声称该扩展代表一种包类型(com.apple.package在输出中mdls -name kMDItemContentTypeTree <foldername>查找以查找。)

  3. 目录的包位已设置(如果GetFileInfo -ab <foldername>返回1,则设置为位。)

情况2。适用于.itmsp文件夹:Application Loader.app导出类型com.apple.itunes-producer.itmsp并将其设置为符合com.apple.package

$ mkdir foo.itmsp
$ mdls -name kMDItemContentTypeTree foo.itmsp/
kMDItemContentTypeTree = (
    "com.apple.itunes-producer.itmsp",
    "com.apple.package",
    (...)
)
$ grep -B 5 -A 8 com.apple.package /Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Info.plist 
    <key>UTExportedTypeDeclarations</key>
    <array>
        <dict>
            <key>UTTypeConformsTo</key>
            <array>
                <string>com.apple.package</string>
                <string>public.composite-content</string>
            </array>
            <key>UTTypeDescription</key>
            <string>iTunes Package</string>
            <key>UTTypeIconFile</key>
            <string>ITMSP.icns</string>
            <key>UTTypeIdentifier</key>
            <string>com.apple.itunes-producer.itmsp</string>

解决方法:重新声明类型 com.apple.itunes-producer.itmsp

一种解决方案是将类型com.apple.itunes-producer.itmsp和扩展名重新声明itmsp文件夹,并强制启动服务使用修改后的类型声明。

重要的提示:

尽管它可以可靠地解决OP的问题,但所提出的解决方案在应用于其他程序包时不会将其显示为文件夹。

我发现,提出的解决方案似乎仅适用于位于非标准应用程序路径中的应用程序声明的文件类型。

Application Loader.app位于的就是这种情况/Applications/Xcode.app/Contents/Applications/

如果您对部分解决方案感兴趣,请查看此答案的结尾。

要使Finder将.itmsp文件夹显示为文件夹,请执行以下步骤:

  1. 在“应用程序”文件夹中打开Automator,然后选择“ 应用程序”

    在此处输入图片说明

  2. 在“库”列表中选择“实用程序”,选择“运行Shell脚本”并将其拖到右侧窗格中:

    在此处输入图片说明

  3. 将默认脚本内容替换为exit 0

    在此处输入图片说明

  4. 将应用程序另存为itmspOpener:

    在此处输入图片说明

  5. 关闭自动器。

  6. 选择itmspOpener.app并显示其内容:

    在此处输入图片说明

  7. 找到目录> Info.plist并使用您喜欢的编辑器将其打开:

    在此处输入图片说明

  8. 将这些部分替换为Info.plist

    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeExtensions</key>
            <array>
                <string>itmsp</string>
            </array>
            <key>CFBundleTypeName</key>
                <string>itmsp folder</string>
            <key>CFBundleTypeRole</key>
                <string>Viewer</string>
            <key>CFBundleTypeIconFile</key>
                <string>folder</string>
            <key>LSTypeIsPackage</key>
                <false/>
            <key>LSHandlerRank</key>
                <string>Owner</string>
        </dict>
    </array>
    (...)
    <key>UTExportedTypeDeclarations</key>
    <array>
        <dict>
            <key>UTTypeConformsTo</key>
            <array>
                <string>kUTTypeDirectory</string>
            </array>
            <key>UTTypeDescription</key>
            <string>itmsp folder</string>
            <key>UTTypeIconFile</key>
            <string>folder.icns</string>
            <key>UTTypeIdentifier</key>
            <string>com.apple.itunes-producer.itmsp</string>
            <key>UTTypeTagSpecification</key>
            <dict>
                <key>public.filename-extension</key>
                <string>itmsp</string>
            </dict>
        </dict>
    </array>
    

    注意: 为什么要kUTTypeDirectory代替public.directoryin UTExportedTypeDeclarations?根据Apple的文档重要提示:在代码中使用系统定义的UTI时,应使用UTCoreTypes.hLaunch Services框架中定义的常量(如果可用),而不是实际的UTI字符串。例如,传递kUTTypeApplication而不是“ com.apple.application”。“系统声明的统一类型标识符”除列出了UTI字符串外,还列出了这些常量。

  9. 将.itmsp文件关联到itmspOpener并按下按钮Change All...

    在此处输入图片说明

  10. 重置启动服务数据库:

    $ lsregister -kill -r -domain local -domain system -domain user
    

    (在OS X 10.8 lsregister中位于/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/。)

  11. 创建一个.itmsp文件夹并列出其属性:

    $ mkdir foo3.itmsp
    $ mdls -name kMDItemContentTypeTree foo3.itmsp/
    kMDItemContentTypeTree = (
        "public.folder",
        "public.directory",
        "public.item"
    )
    

    因为启动服务数据库已重置,所以现在Finder将.itmsp文件夹显示为文件夹。

  12. 打开itmspOpener.app以加载其plist文件并注册com.apple.itunes-producer.itmsp

    $ open ~/Desktop/itmspOpener.app
    
  13. 开始Application Loader.app

    $ open '/Applications/Xcode.app/Contents/Applications/Application Loader.app'
    

    文件夹foo3.itmsp仍应显示为文件夹。

  14. 再次检查文件夹属性:

    $ mdls -name kMDItemContentTypeTree foo3.itmsp/
    kMDItemContentTypeTree = (
        "public.directory",
        "public.item",
        "public.content"
    )
    

    com.apple.package 没有添加到文件夹的元数据属性,这就是Finder仍将.itmsp文件夹显示为文件夹的原因!

自动化解决方案:登录后将.itmsp文件夹显示为文件夹

在登录后将.itmsp文件夹显示为文件夹:

  1. 如上所述创建itmspOpener.app和修改它Info.plist

  2. /usr/local/bin/itmspTypeLoader使用此内容创建(变量itmspOpener指向itmspOpener.app驻留的位置,必要时进行更改):

    #!/bin/bash
    
    itmspOpener="/Users/jaume/Applications/itmspOpener.app/"
    
    echo "$(date): Starting" > /tmp/itmspTypeLoader.log
    sleep 15
    echo "$(date): Deleting Launch Services database" >> /tmp/itmspTypeLoader.log
    /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -kill -r -domain local -domain system -domain user >> /tmp/itmspTypeLoader.log
    sleep 15
    echo "$(date): Starting $itmspOpener" >> /tmp/itmspTypeLoader.log
    open $itmspOpener >> /tmp/itmspTypeLoader.log
    sleep 1
    echo "$(date): Starting Application Loader.app" >> /tmp/itmspTypeLoader.log
    open "/Applications/Xcode.app/Contents/Applications/Application Loader.app/"
    
    # Wait until process "Application Loader.app" exists
    while [ $(ps -ef|grep -v grep|grep -c "Application Loader") -ne 1 ]; do
        sleep 1
        echo "$(date): Waiting" >> /tmp/itmspTypeLoader.log
    done
    # Send TERM signal
    kill -TERM $(ps -ef|grep "Application Loader"|grep -v grep|awk "{print \$2}")
    if [ $? -eq 0 ]; then
        echo "$(date): Application Loader killed" >> /tmp/itmspTypeLoader.log
    else
        echo "$(date): Application Loader could not be killed" >> /tmp/itmspTypeLoader.log
    fi
    echo "$(date): Exiting" >> /tmp/itmspTypeLoader.log
    

    无论sleep 15在运行前后lsregister是最重要的。如果看不到预期的结果,请尝试其他延迟。

  3. /usr/local/bin/itmspTypeLoaderLauncher使用以下内容创建:

    #!/bin/bash
    
    # $1 returns the short name of the user who is logging in
    su - $1 -c /usr/local/bin/itmspTypeLoader &
    
  4. 将两个脚本都设置为可执行文件:

    $ sudo chmod a+x /usr/local/bin/itmspTypeLoader /usr/local/bin/itmspTypeLoaderLauncher 
    
  5. 设置/usr/local/bin/itmspTypeLoaderLauncher登录挂钩

    $ sudo defaults write com.apple.loginwindow LoginHook /usr/local/bin/itmspTypeLoaderLauncher
    
  6. 重新启动以使更改生效。登录后,您应该会看到以下内容:

    在此处输入图片说明

    lsregister -dump应该表明itmspOpener.appUTExportedTypeDeclarations在优先Application Loader.app的:

    $ lsregister -dump | less
    bundle  id:            24748
            path:          /Users/jaume/Desktop/itmspOpener.app/
            name:          itmspOpener
            (...)
            flags:         apple-internal  relative-icon-path  ui-element  has-min-sys-version-by-arch  hi-res-capable  user-can-change-hi-res-mode  
            item flags:    container  package  application  extension-hidden  native-app  scriptable  services  x86_64  
            (...)
            --------------------------------------------------------
            type    id:            33796
                    uti:           com.apple.itunes-producer.itmsp
                    description:   itmsp folder
                    flags:         exported  active  apple-internal  trusted  
                    icon:          Contents/Resources/folder.icns
                    conforms to:   kuttypedirectory
                    tags:          .itmsp
            --------------------------------------------------------
            (...)
    bundle  id:            24600
            path:          /Applications/Xcode.app/Contents/Applications/Application Loader.app/
            name:          Application Loader
            (...)
            flags:         apple-internal  relative-icon-path  hi-res-capable  user-can-change-hi-res-mode  
            item flags:    container  package  application  extension-hidden  native-app  i386  x86_64  
            (...)
            --------------------------------------------------------
            type    id:            33832
                    uti:           com.apple.itunes-producer.itmsp
                    description:   iTunes Package
                    flags:         exported  inactive  apple-internal  trusted  
                    icon:          Contents/Resources/ITMSP.icns
                    conforms to:   com.apple.package, public.composite-content
                    tags:          .itmsp
            --------------------------------------------------------
    

    您是否inactive在Application Loader.app的类型导出中看到设置的标志?我们击败了Application Loader。

酸性测试:.itmsp文件夹在iTunes更新后仍显示为

我最近更新了Xcode:

在此处输入图片说明

并可以确认.itmsp文件夹在更新过程中显示为文件夹:

在此处输入图片说明

然后:

在此处输入图片说明

部分解决方案:双击该软件包将显示内容

如前所述,上面详细介绍的过程不适用于Finder作为包显示的任意文件夹。

但是,如果只想双击一个程序包将其打开,则可以使用一种bash脚本和Automator来实现:

  • 该脚本会在包内创建一个隐藏的临时文件夹,在Finder中将其显示(从而将包显示为文件夹),然后删除该临时文件夹。

    注意:

    该脚本可以创建一个隐藏的临时文件。但是,我更喜欢创建一个文件夹,因为它rmdir只会删除文件夹,而rm删除任何文件,因此会出于某种原因。该脚本造成了严重破坏,只会删除空文件夹,这可能不像删除文件那样糟糕。

  • Automator将该脚本捆绑到将与软件包文件关联的应用程序中。

这些是创建此类应用程序的步骤。在以下说明中,我将使用.itmsp文件作为包类型示例:

  1. 在“应用程序”文件夹中打开Automator,然后选择“ 应用程序”

    在此处输入图片说明

  2. 选择工具在库列表中,选择运行shell脚本并将其拖动到右边的窗格:

    在此处输入图片说明

  3. Pass输入设置为参数

    在此处输入图片说明

  4. 用以下内容替换默认脚本内容:

    for f in "$@"; do
        # If not dealing with a directory, exit
        if [ ! -d "$f" ]; then exit; fi
        # Create a temporary directory inside the itmsp "file"
        tmpdir="$f/.itmspOpener$$"
        if mkdir $tmpdir; then
            # Reveal in Finder
            open -R $tmpdir
            # Delete temporary file
            rmdir $tmpdir
        fi
    done
    
  5. 将应用程序另存为itmspOpener:

    在此处输入图片说明

  6. 关闭自动器。

现在,您有了一个可以将.itmsp文件作为文件夹打开的应用程序。

有一个外观上的问题:就目前而言,关联文件将带有标准的白色文档图标:

在此处输入图片说明

我们也修复此问题:

  1. 确保Automator已关闭。

  2. 选择itmspOpener并显示其内容:

    在此处输入图片说明

  3. 找到目录> Info.plist并使用您喜欢的编辑器将其打开:

    在此处输入图片说明

  4. 替换CFBundleDocumentTypes数组中此键的值:

    <key>CFBundleTypeName</key>
    <string>itmsp folder</string>
    

    并添加以下密钥:

    <key>CFBundleTypeIconFile</key>
    <string>folder</string>
    

    现在,该部分如下所示:

    在此处输入图片说明

  5. 切换到Finder,选择一个文件夹,按I,选择左上角的文件夹图标,然后使用进行复制C

    在此处输入图片说明

  6. 打开预览,然后从剪贴板中选择文件>新建。将文件另存为folder.icns

    在此处输入图片说明

  7. 复制folder.icnsitmspOpener/Contents/Resources

    在此处输入图片说明

  8. 将.itmsp文件关联到itmspOpener并按下按钮Change All...

    在此处输入图片说明

.itmsp文件的图标应该更改为一个文件夹,或者至少我这样认为:不幸的是,事实并非如此。因此,我将应用程序itmspOpener移到了另一个位置(我在桌面上创建了一个临时文件夹,然后将其移回桌面)。刷新了Finder中的图标信息:

在此处输入图片说明

现在,双击.itmsp文件,并观看它作为文件夹打开:

在此处输入图片说明


这给人留下了深刻的印象……但是似乎有一个小问题:如果Finder在列视图(我的首选视图类型)中,则.itmsp文件夹中包含的所有内容都是不可见的。我无法弄清楚为什么,但是确实如此。此外,如果我有德鲁特人,则无需双击文件即可查看内部文件,但是哦。
michaelmichael

1
你是对的。我没想到您会使用列视图,尽管我必须说在处理成千上万个.itmsp文件夹时这是很有意义的。但是我找到了解决问题的方法,即强制Finder将.itmsp文件夹视为文件夹。看一看我的编辑(或直接跳到名为The solution的最后一段,但不要忘记首先按照The窍门一节中的描述修改itmspOpener的Info.plist。)
jaume

难以置信的!感谢您的回答。这是使Finder和OS X滴答作响的一些有趣的发现。
michaelmichael

谢谢,很高兴您发现它有用!(我将在稍后编辑答案以提高可读性并赋予其更多结构。)
Jaume 2013年

我终于找到了一些时间来编辑答案。我对段落进行了重新排序,并添加了证据,证明答案中解释的解决方案不受iTunes更新的影响。
2013年

7

一种选择是使用取消注册Application Loader lsregister -u /Applications/Xcode.app/Contents/Applications/Application\ Loader.app/,但是如果打开了它,重新构建了Launch Services数据库或可能更新了Xcode,则会再次注册它。

您也可以注释掉/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Info.plist并运行CFBundleDocumentTypes和UTExportedTypeDeclarations字典中的条目lsregister -f /Applications/Xcode.app/Contents/Applications/Utilities/Application\ Loader.app/。它不会使Xcode的代码签名无效,但是更改可能会被更新覆盖。

lsregister的完整路径/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister在10.5及更高版本中。


您确定更改应用程序后Info.plist取消注册将取消注册从plist中删除的文件类型吗?我可以想象它能正常工作,而我很容易想象它会失败。太。
Old Pro

@OldPro是的,lsregister -u $app && lsregister $app至少在这种情况下,似乎确实将更改应用于了Info.plist。
Lri 2012年

这是一个很好的答案-请记住,下次升级Xcode时-可能会注册一个注册了默认值的Application Loader,CFBundleDocumentTypes因此如果不需要它,您可以只删除该“工具”,并且/或厌倦修改它。
bmike

2

这是Apple 关于捆绑软件的文档的相关摘录(重点已添加

系统如何识别捆绑和包裹

如果满足以下任一条件,则Finder会将目录视为软件包:

  • 该目录具有已知的文件扩展名:.app,.bundle,.framework,.plugin,.kext等。
  • 该目录的扩展名是其他一些应用程序声称的表示软件包类型的扩展名。请参阅“ 文档包”
  • 该目录设置了其软件包位。

指定软件包的首选方法是给软件包目录一个已知的文件扩展名。在大多数情况下,Xcode通过提供应用正确扩展名的模板来为您解决这一问题。您要做的就是创建适当类型的Xcode项目。

几乎可以肯定Xcode表示它声称.itmsp代表一种包类型,如Document Packages中所述。因此,也许从Xcode删除该扩展名Info.plist就能解决问题,但是我怀疑一旦Finder注意到该关联,从Xcode删除该扩展名就不会撤消它。右键单击“打开方式...”会得到什么“推荐的应用程序”?您需要检查所有他们的Info.plists。

建议您查看是否可以lsregister -u取消注册任何声称拥有所有权的应用程序.itmsp。否则,您可能必须.itmsp从所有plists中删除,然后使用杀死整个finder关联数据库lsregister -kill -seed。从来没有这样做,也没有说会对系统的其余部分造成多大的损害。可能您想注销,然后编辑插件,然后杀死数据库并重新设置其种子。如果您已经从plist中删除,那么如果注销并没有删除该关联,也不会令我感到惊讶。另外,通过这种方式,您不会丢失所有其他与冒犯性应用程序相关的关联。

更糟糕的是,Xcode可能会经历并在所有文件夹上设置bundle bit。我想那您就必须使用脚本来编写脚本GetFileInfoSetFile扫描磁盘并撤消这些脚本,这有点痛苦,但是可行。手指越过捆扎头,未置位。用于GetFileInfo通过测试来检查一些。


0

我相信您可以使用

/usr/bin/SetFile -a B /path/to/file.itmsp

显然,先对其中一个进行测试,然后再对所有其他尝试。

如果需要它在给定文件夹中的所有文件上运行:

find . -name \*.itmsp -exec /usr/bin/SetFile -a B {} \;

应该为你做。


1
SetFile -a B 设置捆绑位。实际上,应该将其禁用:SetFile -a b。但这不会生效,因为Has bundle未设置该位:GetFileInfo -ab foo.itmspreturn 0
2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.