macos获得当前壁纸完整路径

macos 15.6 测试成功

虽然成功,但是不简洁,希望有人优化。

swift代码:

代码片.

#!/usr/bin/env swift

import AppKit
import Foundation

// MARK: - 工具函数

func expandTilde(_ path: String) -> String {
    if path.hasPrefix("~") { return (path as NSString).expandingTildeInPath }
    return path
}

func isDirectory(_ path: String) -> Bool {
    var isDir: ObjCBool = false
    let exists = FileManager.default.fileExists(atPath: path, isDirectory: &isDir)
    return exists && isDir.boolValue
}

func isFile(_ path: String) -> Bool {
    var isDir: ObjCBool = false
    let exists = FileManager.default.fileExists(atPath: path, isDirectory: &isDir)
    return exists && !isDir.boolValue
}

@discardableResult
func runShell(_ command: String) -> (status: Int32, stdout: String, stderr: String) {
    let task = Process()
    task.executableURL = URL(fileURLWithPath: "/bin/zsh")
    task.arguments = ["-lc", command]
    let outPipe = Pipe()
    let errPipe = Pipe()
    task.standardOutput = outPipe
    task.standardError = errPipe
    do { try task.run() } catch {
        return (status: -1, stdout: "", stderr: "执行失败: \(error)")
    }
    task.waitUntilExit()
    let outData = outPipe.fileHandleForReading.readDataToEndOfFile()
    let errData = errPipe.fileHandleForReading.readDataToEndOfFile()
    let outStr = String(data: outData, encoding: .utf8) ?? ""
    let errStr = String(data: errData, encoding: .utf8) ?? ""
    return (status: task.terminationStatus, stdout: outStr, stderr: errStr)
}

// 通过 System Events 获取当前桌面图片路径(可能返回目录)
func getSystemEventsDesktopPicture() -> String? {
    let source = """
    tell application "System Events"
        tell current desktop
            set wallpaperPath to picture
        end tell
    end tell
    """
    var errorInfo: NSDictionary?
    guard let script = NSAppleScript(source: source) else { return nil }
    let result = script.executeAndReturnError(&errorInfo)
    if errorInfo != nil { return nil }
    return result.stringValue
}

// 通过 Finder 获取当前桌面图片的完整信息
func getFinderDesktopPictureInfo() -> (name: String?, path: String?) {
    let source = """
    tell application "Finder"
        try
            set theDesktopPic to desktop picture
            set theName to displayed name of theDesktopPic
            set thePath to POSIX path of theDesktopPic
            return {theName, thePath}
        on error errMsg
            return {"", ""}
        end try
    end tell
    """
    var errorInfo: NSDictionary?
    guard let script = NSAppleScript(source: source) else { return (nil, nil) }
    let result = script.executeAndReturnError(&errorInfo)
    if errorInfo != nil { return (nil, nil) }
    
    let output = result.stringValue ?? ""
    let components = output.components(separatedBy: ", ")
    let name = components.first?.trimmingCharacters(in: .whitespacesAndNewlines)
    let path = components.count > 1 ? components[1].trimmingCharacters(in: .whitespacesAndNewlines) : nil
    
    return (name, path)
}

// 获取目录中最可能是当前壁纸的文件
func getCurrentWallpaperFile(in directory: String) -> String? {
    guard let urls = try? FileManager.default.contentsOfDirectory(
        at: URL(fileURLWithPath: directory),
        includingPropertiesForKeys: [.contentAccessDateKey, .contentModificationDateKey, .creationDateKey, .fileSizeKey],
        options: [.skipsHiddenFiles]
    ) else { return nil }
    
    let imageExts: Set<String> = ["jpg","jpeg","png","heic","tiff","bmp","gif","webp"]
    let candidates = urls.filter { !$0.hasDirectoryPath && imageExts.contains($0.pathExtension.lowercased()) }
    
    // 多种策略来找到当前壁纸
    var bestCandidate: URL? = nil
    var bestScore = -1
    
    for url in candidates {
        var score = 0
        
        // 策略1: 最近修改的文件得分更高
        if let modDate = try? url.resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate {
            let hoursSinceMod = Date().timeIntervalSince(modDate) / 3600
            if hoursSinceMod < 24 { score += 10 }  // 24小时内修改
            else if hoursSinceMod < 168 { score += 5 }  // 一周内修改
        }
        
        // 策略2: 文件大小适中的图片(排除过小或过大的文件)
        if let fileSize = try? url.resourceValues(forKeys: [.fileSizeKey]).fileSize {
            let sizeMB = Double(fileSize) / 1024 / 1024
            if sizeMB >= 0.1 && sizeMB <= 10.0 { score += 5 }  // 100KB-10MB
            else if sizeMB > 10.0 { score += 2 }  // 大于10MB
        }
        
        // 策略4: 最近创建的文件得分更高
        if let createDate = try? url.resourceValues(forKeys: [.creationDateKey]).creationDate {
            let hoursSinceCreate = Date().timeIntervalSince(createDate) / 3600
            if hoursSinceCreate < 24 { score += 3 }
        }
        
        if score > bestScore {
            bestScore = score
            bestCandidate = url
        }
    }
    
    return bestCandidate?.path
}

// 简化的 Wallpaper 进程查询(只查询一次)
func findWallpaperViaProcessFiles() -> (current: String?, next: String?) {
    print("正在检查Wallpaper进程打开的文件...")
    
    // 只使用一个最有效的查询
    let cmd = "lsof | grep Wallpaper | grep -E '\\.(png|heic|jpg|jpeg)' | head -6"
    let result = runShell(cmd)
    
    var foundFiles: [String] = []
    
    if !result.stdout.isEmpty {
        // 过滤掉空行并打印
        let lines = result.stdout.components(separatedBy: "\n").filter { !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }
        for line in lines {
            print(line)
        }
        
        // 快速解析输出
        for line in lines {
            // 提取文件路径(通常在行的最后)
            let components = line.components(separatedBy: " ")
            for component in components {
                // 检查是否是图片文件路径
                if (component.contains(".png") || component.contains(".heic") || component.contains(".jpg") || component.contains(".jpeg")) {
                    let path = component.trimmingCharacters(in: .whitespacesAndNewlines)
                    if FileManager.default.fileExists(atPath: path) {
                        foundFiles.append(path)
                    }
                }
            }
        }
    }
    
    // 返回第一个作为当前壁纸,第二个作为下一个壁纸
    let current = foundFiles.first
    let next = foundFiles.count > 1 ? foundFiles[1] : nil
    
    return (current, next)
}

// MARK: - 主流程

print("正在获取当前壁纸信息...")

// 1) 尝试通过 Finder 获取完整信息
let finderInfo = getFinderDesktopPictureInfo()
if let finderName = finderInfo.name, let finderPath = finderInfo.path {
    print("Finder 返回的壁纸名称: \(finderName)")
    print("Finder 返回的路径: \(finderPath)")
    
    let expandedFinderPath = expandTilde(finderPath)
    if isFile(expandedFinderPath) {
        let filename = URL(fileURLWithPath: expandedFinderPath).lastPathComponent
        print("显示器 1 的壁纸: \(filename)")
        print("完整路径: \(expandedFinderPath)")
    } else if isDirectory(expandedFinderPath) {
        // 使用最新访问的图片
        if let latestPath = getCurrentWallpaperFile(in: expandedFinderPath) {
            let filename = URL(fileURLWithPath: latestPath).lastPathComponent
            print("显示器 1 的壁纸: \(filename)")
            print("完整路径: \(latestPath)")
            
            if let accessDate = try? URL(fileURLWithPath: latestPath).resourceValues(forKeys: [.contentAccessDateKey]).contentAccessDate {
                let formatter = DateFormatter()
                formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
                print("文件访问时间: \(formatter.string(from: accessDate))")
            }
        }
    }
} else {
    print("无法通过 Finder 获取壁纸信息")
    
    // 备用方案:使用 System Events
    if let sePath = getSystemEventsDesktopPicture() {
        let expandedPath = expandTilde(sePath)
        print("System Events 返回的路径: \(expandedPath)")
        
        if isDirectory(expandedPath) {
            if let latestPath = getCurrentWallpaperFile(in: expandedPath) {
                let filename = URL(fileURLWithPath: latestPath).lastPathComponent
                print("显示器 1 的壁纸: \(filename)")
                print("完整路径: \(latestPath)")
                
                if let accessDate = try? URL(fileURLWithPath: latestPath).resourceValues(forKeys: [.contentAccessDateKey]).contentAccessDate {
                    let formatter = DateFormatter()
                    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
                    print("文件访问时间: \(formatter.string(from: accessDate))")
                }
            } else {
                print("显示器 1 的壁纸: 未找到图片文件")
            }
        } else if isFile(expandedPath) {
            let filename = URL(fileURLWithPath: expandedPath).lastPathComponent
            print("显示器 1 的壁纸: \(filename)")
            print("完整路径: \(expandedPath)")
        }
    }
}

// 2) 通过 Wallpaper 进程找到当前壁纸(最有效的方法)
let wallpaperFiles = findWallpaperViaProcessFiles()

if let currentPath = wallpaperFiles.current {
    let filename = URL(fileURLWithPath: currentPath).lastPathComponent
    print("当前壁纸: \(filename)")
    print("完整路径: \(currentPath)")
    
    // 显示文件详细信息
    let url = URL(fileURLWithPath: currentPath)
    if let accessDate = try? url.resourceValues(forKeys: [.contentAccessDateKey]).contentAccessDate {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        print("访问时间: \(formatter.string(from: accessDate))")
    }
    
    if let fileSize = try? url.resourceValues(forKeys: [.fileSizeKey]).fileSize {
        let sizeMB = Double(fileSize) / 1024 / 1024
        print("文件大小: \(String(format: "%.2f", sizeMB)) MB")
    }
    
    // 打开图片
    print("正在打开图片...")
    let openResult = runShell("open '\(currentPath)'")
    if openResult.status == 0 {
        print("图片已打开")
    } else {
        print("打开图片失败")
    }
    
    // 提供交互选项
    print("是否删除这个壁纸文件?(y/n): ", terminator: "")
    if let input = readLine()?.lowercased() {
        if input == "y" || input == "yes" {
            do {
                try FileManager.default.removeItem(atPath: currentPath)
                print("文件已删除")
            } catch {
                print("删除文件失败: \(error)")
            }
        } else {
            print("文件保留")
        }
    }
    
    // 如果有下一个壁纸,也显示
    if let nextPath = wallpaperFiles.next {
        let nextFilename = URL(fileURLWithPath: nextPath).lastPathComponent
        print("下一个壁纸: \(nextFilename)")
        print("完整路径: \(nextPath)")
    }
}

print("壁纸获取完成。")

更多推荐