You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用FileManager和NSBundle获取/Applications目录下支持指定文件类型的所有应用

实现方案

核心逻辑

  • 第一步用FileManager遍历/Applications目录下所有后缀为.app的应用包
  • 第二步对每个.app包,通过Bundle读取其Info.plist中的CFBundleDocumentTypes字段,该字段存储了应用官方声明支持的所有文档类型
  • 第三步匹配该字段下的CFBundleTypeExtensions数组,判断是否包含用户输入的扩展名,匹配成功则记录对应应用名称

完整可运行代码示例

import Foundation

// 接收用户输入的目标扩展名
print("请输入要查询的文件扩展名(例如mp4):")
guard let targetExt = readLine()?.lowercased(), !targetExt.isEmpty else {
    print("输入不能为空")
    exit(1)
}

let fileManager = FileManager.default
let systemAppsDir = URL(fileURLWithPath: "/Applications", isDirectory: true)
var matchedApps = [String]()

do {
    // 遍历应用目录,配置跳过隐藏文件、不进入包内部遍历,提升执行效率
    let dirItems = try fileManager.contentsOfDirectory(at: systemAppsDir, includingPropertiesForKeys: [.isDirectoryKey], options: [.skipsHiddenFiles, .skipsPackageDescendants])
    
    for item in dirItems {
        // 筛选合法的.app应用包
        guard item.pathExtension == "app",
              let isDirectory = try? item.resourceValues(forKeys: [.isDirectoryKey]).isDirectory,
              isDirectory == true else {
            continue
        }
        
        // 加载应用对应的Bundle实例
        guard let appBundle = Bundle(url: item) else {
            continue
        }
        
        // 读取应用支持的文档类型配置
        guard let documentTypes = appBundle.infoDictionary?["CFBundleDocumentTypes"] as? [[String: Any]] else {
            continue
        }
        
        // 匹配扩展名
        for docType in documentTypes {
            guard let supportedExts = docType["CFBundleTypeExtensions"] as? [String] else {
                continue
            }
            if supportedExts.map({ $0.lowercased() }).contains(targetExt) {
                if let appName = appBundle.infoDictionary?["CFBundleName"] as? String, !matchedApps.contains(appName) {
                    matchedApps.append(appName)
                }
                break
            }
        }
    }
    
    // 输出结果
    if matchedApps.isEmpty {
        print("未找到支持.\(targetExt)格式的应用")
    } else {
        print("支持.\(targetExt)格式的应用如下:")
        matchedApps.forEach { print("- \($0)") }
    }
} catch {
    print("遍历应用目录失败:\(error.localizedDescription)")
    exit(1)
}

关键注意点

  • 如果需要同时搜索当前用户目录下的~/Applications路径,可自行添加对应目录的遍历逻辑
  • 遍历参数中设置skipsPackageDescendants可避免进入.app包内部遍历,执行速度提升非常明显
  • 部分小众应用未按规范填写Info.plist的CFBundleTypeExtensions字段,会出现匹配不到的情况,属于应用本身配置问题,不属于代码逻辑问题
  • 普通用户权限即可正常遍历/Applications目录,不需要申请特殊权限

内容的提问来源于stack exchange,提问作者user11875731

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 08:48:02