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 of mdls -name kMDItemContentTypeTree <foldername>
to find out.)
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:
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 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.
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 register com.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 its Info.plist
as described above.
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.
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 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:
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, 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:
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
to itmspOpener/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: