Revert Filetype Association

The problem: .itmsp folders are shown as files

The Finder treats .itmsp folders as packages, that is, as if they were a single file. For example, in column view, anything contained within the .itmsp folder is invisible, only the document icon is shown:

enter image description here

The Finder considers a directory to be a package if any of the following conditions is true (from the Bundle Programming Guide):

  1. The directory has a known filename extension: .app, .bundle, .framework, .plugin, .kext, and so on (as defined in /System/Library/CoreServices/CoreTypes.bundle/Contents/Info.plist. This is a binary plist, open it with Xcode: open -a Xcode Info.plist).

  2. The directory has an extension that some other application claims represents a package type (look for com.apple.package in the output of mdls -name kMDItemContentTypeTree <foldername> to find out.)

  3. The directory has its package bit set (if GetFileInfo -ab <foldername> returns 1, it is set.)

Case 2. applies to .itmsp folders: Application Loader.app exports type com.apple.itunes-producer.itmsp and sets it to conform to 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>

A solution: re-declare type com.apple.itunes-producer.itmsp

A solution would be to re-declare type com.apple.itunes-producer.itmsp and extension itmsp as a folder and force Launch Services to use the modified type declaration.

Important note:

Although it reliably solves the OP's problem, the proposed solution, when applied to other packages, doesn't display them as folders.

I've found out that the proposed solution seems to work only with file types declared by applications located in an non standard application path.

This is the case with Application Loader.app, which is located in /Applications/Xcode.app/Contents/Applications/.

If you are interested in a partial solution check the end of this answer.

To have .itmsp folders be displayed as folders by the Finder follow the next steps:

  1. Open Automator in the Applications folder and select Application:

    enter image description here

  2. Select Utilities in the Library list, select Run Shell Script and drag it to the pane on the right:

    enter image description here

  3. Replace the default script contents with exit 0:

    enter image description here

  4. Save the application as itmspOpener:

    enter image description here

  5. Close Automator.

  6. Select itmspOpener.app and show its contents:

    enter image description here

  7. Locate Contents>Info.plist and open it with your favorite editor:

    enter image description here

  8. Replace these sections in 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>
    

    Note: Why kUTTypeDirectory instead of public.directory in UTExportedTypeDeclarations? From Apple's documentation: Important: When using system-defined UTIs in your code, you should use the constants defined in UTCoreTypes.h in the Launch Services framework when available, rather than the actual UTI strings. For example, pass kUTTypeApplication rather than “com.apple.application”. “System-Declared Uniform Type Identifiers ” lists these constants in addition to the UTI strings.

  9. Associate a .itmsp file to itmspOpener and press the button Change All...:

    enter image description here

  10. Reset the Launch Services database:

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

    (on OS X 10.8 lsregister is located in /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/.)

  11. Create a .itmsp folder and list its properties:

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

    Because the Launch Services database was reset, now the Finder shows .itmsp folders as folders.

  12. Open itmspOpener.app to load its plist file and register com.apple.itunes-producer.itmsp:

    $ open ~/Desktop/itmspOpener.app
    
  13. Start Application Loader.app:

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

    Folder foo3.itmsp should still be displayed as a folder.

  14. Check the folder properties again:

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

    com.apple.package wasn't added to the folder's metadata attributes, that's why the Finder still displays .itmsp folders as folders!

Automated solution: displaying .itmsp folders as folders after login

To display .itmsp folders as folders after login:

  1. Create itmspOpener.app and modify its Info.plist as described above.

  2. Create /usr/local/bin/itmspTypeLoader with this contents (the variable itmspOpener points to the location where itmspOpener.app resides, change as necessary):

    #!/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
    

    Both sleep 15 before and after running lsregister are of utmost importance. If you don't see the desired result, try different delays.

  3. Create /usr/local/bin/itmspTypeLoaderLauncher with this contents:

    #!/bin/bash
    
    # $1 returns the short name of the user who is logging in
    su - $1 -c /usr/local/bin/itmspTypeLoader &
    
  4. Set both scripts executable:

    $ sudo chmod a+x /usr/local/bin/itmspTypeLoader /usr/local/bin/itmspTypeLoaderLauncher 
    
  5. Set /usr/local/bin/itmspTypeLoaderLauncher as login hook:

    $ sudo defaults write com.apple.loginwindow LoginHook /usr/local/bin/itmspTypeLoaderLauncher
    
  6. Reboot for changes to take effect. After logging in you should see this:

    enter image description here

    and lsregister -dump should reveal that itmspOpener.app's UTExportedTypeDeclarations takes precedence over Application Loader.app's:

    $ 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
            --------------------------------------------------------
    

    Do you see the inactive flag set in Application Loader.app's type export? We defeated Application Loader.

The acid test: .itmsp folders still displayed as such after iTunes update

I recently updated Xcode:

enter image description here

and can confirm that .itmsp folders were shown as folders during the update:

enter image description here

and afterwards:

enter image description here

A partial solution: The package will show contents when double clicked

As commented previously, the procedure detailed above won't work with arbitrary folders that are displayed as packages by the Finder.

However, if you just want to be able to double-click a package to open it, there is a way to do it with one bash script and Automator:

  • The script creates a hidden, temporary folder inside the package, reveals it in the Finder (thus revealing the package as a folder) and then deletes the temporary folder.

    Note:

    The script could instead create a hidden, temporary file. However, I prefer to create a folder because rmdir only deletes empty folders, while rm deletes any file, so if, for some reason. the script wreaks havoc, only empty folders will be deleted, which is probably not as bad as if files were deleted.

  • Automator bundles the script into an application that will be associated with the package files.

These are the steps to create such an application. I'll use .itmsp files as a package type example in the explanation below:

  1. Open Automator in the Applications folder and select Application:

    enter image description here

  2. Select Utilities in the Library list, select Run Shell Script and drag it to the pane on the right:

    enter image description here

  3. Set Pass input to as arguments:

    enter image description here

  4. Replace the default script contents with this:

    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. Save the application as itmspOpener:

    enter image description here

  6. Close Automator.

Now you have an application that can open .itmsp files as folders if associated with it.

There's a cosmetic problem: as it stands, associated files will have the standard white document icon:

enter image description here

Let's fix this, too:

  1. Make sure Automator is closed.

  2. Select itmspOpener and show its contents:

    enter image description here

  3. Locate Contents>Info.plist and open it with your favorite editor:

    enter image description here

  4. Replace the value for this key in the CFBundleDocumentTypes array:

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

    and add this key:

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

    Now, the section looks like this:

    enter image description here

  5. Switch to the Finder, select a folder, press I, select the folder icon in the left top corner and copy it with C:

    enter image description here

  6. Open Preview and select File>New from Clipboard. Save the file as folder.icns:

    enter image description here

  7. Copy folder.icns to itmspOpener/Contents/Resources:

    enter image description here

  8. Associate a .itmsp file to itmspOpener and press the button Change All...:

    enter image description here

The icon of .itmsp files should change to a folder, or at least I thought so: unfortunately, this wasn't the case. So I moved the application itmspOpener to another location (I created a temporary folder on my Desktop, moved it there and back to my Desktop). That refreshed the icon information in the Finder:

enter image description here

Now double click a .itmsp file and watch it open as a folder:

enter image description here


One option would be to unregister Application Loader with lsregister -u /Applications/Xcode.app/Contents/Applications/Application\ Loader.app/, but it is registered again if it is opened, if the Launch Services database is rebuilt, or possibly if Xcode is updated.

You could also comment out the entries in the CFBundleDocumentTypes and UTExportedTypeDeclarations dictionaries in /Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Info.plist and run lsregister -f /Applications/Xcode.app/Contents/Applications/Utilities/Application\ Loader.app/. It doesn't invalidate Xcode's code signature, but the changes could get overwritten by updates.

The full path to lsregister is /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister in 10.5 and later.


Here's a relevant excerpt from Apple's documenation about bundles (emphasis added)

How the System Identifies Bundles and Packages

The Finder considers a directory to be a package if any of the following conditions are true:

  • The directory has a known filename extension: .app, .bundle, .framework, .plugin, .kext, and so on.
  • The directory has an extension that some other application claims represents a package type; see “Document Packages.”
  • The directory has its package bit set.

The preferred way to specify a package is to give the package directory a known filename extension. For the most part, Xcode takes care of this for you by providing templates that apply the correct extension. All you have to do is create an Xcode project of the appropriate type.

Almost certainly Xcode is representing that it claims .itmsp represents a package type, as described in Document Packages. So maybe removing that extension from Xcode's Info.plist will do the trick, but I suspect that once that association has been noted by the Finder, removing it from Xcode won't undo it. What are the "recommended applications" you get when you right-click on "Open With..."? You need to check all of their Info.plists.

I suggest seeing if you can get away with using lsregister -u to unregister any apps that claimed .itmsp. Otherwise you might have to remove .itmsp from all the plists and then kill the whole finder association database using lsregister -kill -seed. Never did that, no telling how much damage that will do to the rest of your system. Probably you want to unregister, then edit the plists, then kill and reseed the database. Wouldn't surprise me if unregister doesn't delete the association if you've removed from the plist already, and reseed will add it back in if you haven't removed it yet. Plus this way you won't lose all the other associations for the offending apps.

What's worse, Xcode could have gone through and set the bundle bit on all the folders. I guess then you'd have to write a script using GetFileInfo and SetFile to scan the disk and undo those, which is kind of a pain, but doable. Fingers crossed the bundle bits remain unset. Use GetFileInfo to check by testing a few.