Last active
July 14, 2024 11:52
-
-
Save Clustmart/707fe005fecc1efcb7fe51b3ff8d1e42 to your computer and use it in GitHub Desktop.
Export Safari bookmarks and folder structure to ~/bookmarks.csv
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
// Define the file path to save the CSV | |
let filePath = FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent("bookmarks.csv") | |
// Create the CSV file if it doesn't exist | |
if !FileManager.default.fileExists(atPath: filePath.path) { | |
FileManager.default.createFile(atPath: filePath.path, contents: nil, attributes: nil) | |
} | |
// Open the file handle for writing | |
guard let fileHandle = try? FileHandle(forWritingTo: filePath) else { | |
print("Failed to open file for writing.") | |
exit(1) | |
} | |
defer { | |
fileHandle.closeFile() | |
} | |
// Write the CSV headers | |
let headers = "Website name,URL,Bookmark path\n" | |
fileHandle.write(headers.data(using: .utf8)!) | |
// Get all bookmarks | |
let bookmarksPlistPath = "\(NSHomeDirectory())/Library/Safari/Bookmarks.plist" | |
let bookmarksData = try! Data(contentsOf: URL(fileURLWithPath: bookmarksPlistPath)) | |
let plist = try! PropertyListSerialization.propertyList(from: bookmarksData, options: [], format: nil) | |
// Recursive function to get all bookmarks with their parent folders | |
func getAllBookmarks(bookmarks: [[String: Any]], parentFolders: [String]) -> [[String]] { | |
var results: [[String]] = [] | |
for bookmark in bookmarks { | |
if let url = bookmark["URLString"] as? String, | |
let uriDictionary = bookmark["URIDictionary"] as? [String: Any], | |
let name = uriDictionary["title"] as? String { | |
let bookmarkPath = parentFolders.joined(separator: " > ") | |
results.append([name, url, bookmarkPath]) | |
} | |
if let children = bookmark["Children"] as? [[String: Any]] { | |
let newParentFolders = parentFolders + [bookmark["Title"] as! String] | |
results += getAllBookmarks(bookmarks: children, parentFolders: newParentFolders) | |
} | |
} | |
return results | |
} | |
// Call the recursive function to get all bookmarks with their parent folders | |
let allBookmarks = getAllBookmarks(bookmarks: (plist as! NSDictionary)["Children"] as! [[String: Any]], parentFolders: []) | |
// Write the bookmarks to the CSV | |
for bookmark in allBookmarks { | |
let line = "\(bookmark[0]),\(bookmark[1]),\(bookmark[2])\n" | |
fileHandle.write(line.data(using: .utf8)!) | |
} | |
print("Bookmarks exported to: \(filePath)") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I couldn't replicate your issue. The error import: command not found indicates that the import statement is being interpreted as a shell command rather than a valid Swift language construct. This typically happens when you try to execute a Swift script using a shell interpreter.
You should make sure that swift is installed (execute swift --version). Executing swift export-safari-bookmarks-new.swift is correct, it works on my system.