OSX上清理app的打开文件类型

Mon 16 June 2014 | tags: OS X

例如,浏览器chromium的Info.plist里指定了关联txt格式文件,这样你一旦打开了chromium的所在文件夹,chromium跟txt文件的关联就自动建立了,于是你右键选择txt文件时,open with列表里就多了chromium。

但是至少对于我来说,很多应用我跟本不需要用它来打开某些格式的文件,但是因为这个自动注册的机制,导致open with列表很长,于是我就应该将没有的清理掉。

#!/usr/bin/env python2.7

import plistlib
import os
import sys
import shutil
import subprocess

SUBDIR_PATH=os.path.sep.join(('Contents', 'Info.plist'))

class FileTypeCleaner(object):

    def __init__(self,pathOfFile):
        self.filepath = self.checkInfoPlistExistence(pathOfFile)
        if self.filepath is not None:
            try:
                self.plistdata = plistlib.readPlist(self.filepath)
            except:
                try:
                    self.plistdata = plistlib.readPlistFromString(
                        self.binary2xml(self.filepath))
                except:
                    self.plistdata = None
        else:
            self.plistdata = None

    @staticmethod
    def checkInfoPlistExistence(pathOfFile):
        path=os.path.sep.join((pathOfFile, SUBDIR_PATH))
        if os.path.isfile(path):
            return path
        return None

    def checkInfoPlistHasTypeKey(self):
        if 'CFBundleDocumentTypes' not in self.plistdata or \
                self.plistdata['CFBundleDocumentTypes'] == []:
            return False
        return True

    def vacuumTypeKey(self):
        self.plistdata['CFBundleDocumentTypes'] = []

    @staticmethod
    def binary2xml(pathOfFile):
        commandline = 'plutil -convert xml1 -o - -- ' + pathOfFile
        run = subprocess.Popen(commandline, shell=True, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        plistString, dummy = run.communicate()
        if run.returncode == 0:
            return plistString
        return None


if __name__=='__main__':
    if len(sys.argv)==1:
        sys.stderr.write('Usage: cleanFTypeAssoc.py app1.app [app2.app ...]\n')
        sys.stderr.flush()
        raise SystemExit
    for f in sys.argv[1:]:
        p = FileTypeCleaner(f)
        if p.plistdata is not None:
            if p.checkInfoPlistHasTypeKey():
                p.vacuumTypeKey()
                shutil.move(p.filepath, p.filepath+'~')
                plistlib.writePlist(p.plistdata, p.filepath)