13

I occasionally work with iTunes Music Store packages. These packages have a .itmsp extension. Like .app, .itmsp is essentially a container directory. .itmsp folders contain XML and media files.

The latest Xcode and/or Mac OS X update (Xcode 4.6.1 on Mac OS 10.8.3) has hijacked the filetype association for directories with the .itmsp extension. Previously they were treated like normal folders -- no double-click required to see inside. Now, I have to double-click them to interact with them. When I do, a program called Application Loader tries to open them. In order to see inside I have to right-click and select "Show Package Contents". I'm dealing with thousands of these files at any given time, so that won't work.

I've tried changing or removing the filetype association using Get Info and RCDefaultApp. Neither works. Removing the filetype association simply turns .itmsp directories into blank files. So does deleting Application Loader.app entirely. In either case I still can't browse the contents without right-clicking.

The previously accepted answer worked a treat for a while: lsregister -u /Applications/Contents/Applications/Application\ Loader.app/ It's stopped working since I updated Xcode and/or Mac OS X. If you have Xcode installed, you should be able to test this yourself by naming a directory foo.itmsp.

How can I make it so .itmsp files are treated as folders once again?

4
  • Have you tried dragging and dropping a file on the Xcode App Icon and see if it does what you want?
    – MrDaniel
    Commented Apr 23, 2012 at 18:58
  • Thanks for the suggestion. It's not relevant to the issue at hand, so I'll try to edit my question to clarify my intent. Commented Apr 23, 2012 at 22:46
  • 1
    What version of OS X are you running? What version of Xcode?
    – Old Pro
    Commented Apr 26, 2012 at 7:36
  • I deleted my Answer which did the remove the types from the CFBundleDocumentTypes and kill on the Launch Service DataBase. It works for a while but it appears to reassert its self again at some point later on.??
    – markhunte
    Commented Mar 29, 2013 at 18:05

4 Answers 4

12
+500

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

5
  • This is very impressive... BUT it seems to have one niggling issue: If the Finder is in column view (my preferred view type), anything contained within the .itmsp folder is invisible. I can't sort out why, but there it is. Additionally, if I had my druthers, you wouldn't have to double-click the file to see inside, but oh well. Commented Mar 26, 2013 at 23:25
  • 1
    You are right. I didn't anticipate you used column view, although I must say it makes perfect sense when dealing with thousand of .itmsp folders. But I found a way to solve the problem, that is, force the Finder to treat .itmsp folders as folders. Take a look at my edit (or jump directly to the last paragraph called The solution, but don't forget to modify itmspOpener's Info.plist first as described in paragraph The trick .)
    – jaume
    Commented Mar 28, 2013 at 16:19
  • Unbelievable! Thanks for the answer. This is a very interesting look at some of the things that make the Finder and OS X tick. Commented Mar 28, 2013 at 18:02
  • Thanks, I'm glad you found it useful! (I will edit the answer later to improve readibility and give it more structure.)
    – jaume
    Commented Mar 29, 2013 at 10:01
  • I finally found some time to edit the answer. I have reordered paragraphs and added evidence that the solution explained in my answer is immune to iTunes updates.
    – jaume
    Commented May 10, 2013 at 22:44
7
+350

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.

3
  • Are you sure that unregistering the app after changing its Info.plist will unregister the file types you removed from the plist? I can imagine it working and I can easily imagine it failing. too.
    – Old Pro
    Commented Apr 26, 2012 at 16:34
  • @OldPro Yeah, lsregister -u $app && lsregister $app does seem to apply the changes to an Info.plist at least in this case.
    – Lri
    Commented Apr 26, 2012 at 16:56
  • This is a fabulous answer - keep in mind that the next time you upgrade Xcode - you may end up with an Application Loader that registers the default CFBundleDocumentTypes so you might just delete that "tool" when it appears if you don't need it and/or tire of modifying it.
    – bmike
    Commented Apr 26, 2012 at 18:46
2

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.

0

I believe that you can fix this using

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

Test it on one before you try it on all of the others, obviously.

If you need it to run on all of them in a given folder:

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

should do it for you.

1
  • 1
    SetFile -a B sets the bundle bit. In fact, it should be disabled: SetFile -a b. But this won't have effect since the Has bundle bit is not set: GetFileInfo -ab foo.itmsp returns 0.
    – jaume
    Commented Mar 28, 2013 at 14:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .