macos用swift脚本获得当前壁纸完整路径
·
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("壁纸获取完成。")
更多推荐


所有评论(0)