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:
The Finder considers a directory to be a package if any of the following conditions is true (from the Bundle Programming Guide):
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
).The directory has an extension that some other application claims represents a package type (look for
com.apple.package
in the output ofmdls -name kMDItemContentTypeTree <foldername>
to find out.)The directory has its package bit set (if
GetFileInfo -ab <foldername>
returns1
, 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:
-
Open Automator in the Applications folder and select Application:
-
Select Utilities in the Library list, select Run Shell Script and drag it to the pane on the right:
-
Replace the default script contents with
exit 0
: -
Save the application as itmspOpener:
Close Automator.
-
Select
itmspOpener.app
and show its contents: -
Locate Contents>Info.plist and open it with your favorite editor:
-
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 ofpublic.directory
inUTExportedTypeDeclarations
? From Apple's documentation: Important: When using system-defined UTIs in your code, you should use the constants defined inUTCoreTypes.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. -
Associate a .itmsp file to
itmspOpener
and press the button Change All...: -
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/
.) -
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.
-
Open
itmspOpener.app
to load its plist file and registercom.apple.itunes-producer.itmsp
:$ open ~/Desktop/itmspOpener.app
-
Start
Application Loader.app
:$ open '/Applications/Xcode.app/Contents/Applications/Application Loader.app'
Folder
foo3.itmsp
should still be displayed as a folder. -
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:
Create
itmspOpener.app
and modify itsInfo.plist
as described above.-
Create
/usr/local/bin/itmspTypeLoader
with this contents (the variableitmspOpener
points to the location whereitmspOpener.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 runninglsregister
are of utmost importance. If you don't see the desired result, try different delays. -
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 &
-
Set both scripts executable:
$ sudo chmod a+x /usr/local/bin/itmspTypeLoader /usr/local/bin/itmspTypeLoaderLauncher
-
Set
/usr/local/bin/itmspTypeLoaderLauncher
as login hook:$ sudo defaults write com.apple.loginwindow LoginHook /usr/local/bin/itmspTypeLoaderLauncher
-
Reboot for changes to take effect. After logging in you should see this:
and
lsregister -dump
should reveal thatitmspOpener.app
'sUTExportedTypeDeclarations
takes precedence overApplication 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:
and can confirm that .itmsp folders were shown as folders during the update:
and afterwards:
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, whilerm
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:
-
Open Automator in the Applications folder and select Application:
-
Select Utilities in the Library list, select Run Shell Script and drag it to the pane on the right:
-
Set Pass input to as arguments:
-
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
-
Save the application as itmspOpener:
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:
Let's fix this, too:
Make sure Automator is closed.
-
Select itmspOpener and show its contents:
-
Locate Contents>Info.plist and open it with your favorite editor:
-
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:
-
Switch to the Finder, select a folder, press ⌘I, select the folder icon in the left top corner and copy it with ⌘C:
-
Open Preview and select File>New from Clipboard. Save the file as
folder.icns
: -
Copy
folder.icns
toitmspOpener/Contents/Resources
: -
Associate a .itmsp file to
itmspOpener
and press the button Change All...:
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:
Now double click a .itmsp file and watch it open as a folder:
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.