I use Safari's Reading List to transfer pages from my phone to my computer. But I don't really want to read these in Safari on my desktop. I'd rather read them in Firefox, maybe through Pinboard, which has an API to write items and mark them as "to read". This blog post documents what I learned.
Update: [2014-06-07] Deleting items out of the reading list does not work properly. It's ok to read everything out of there but I haven't figured out how to properly modify it. So I guess I need to delete things manually after I read them out.
Update: [2014-09-18] With iOS 8, I'm switching from Reading List to something else, maybe Pinner, to make this process easier.
I searched the web for some resources, and learned that the reading list, as well as other Safari bookmarks, are stored in
~/Library/Safari/Bookmarks.plist. I can use
PlistBuddy to read and edit that file.
Here's the simplest way for me to get the data in json format (unfortunately
plutil can't directly convert it to json because it won't convert dates to strings):
plutil -convert xml1 ~/Library/Safari/Bookmarks.plist -o - \ | sed -e 's/date>/string>/g' -e 's/data>/string>/g' \ | plutil -convert json -r - -o - >bookmarks.json
Ideally I'd also be able to delete the reading list from Safari when I transfer it elsewhere. To do that, I need to figure out which element(s) to delete.
Looking at the structure of the bookmarks file,
Children is an array of bookmarks, and one of those is the Reading List folder. How do I find the index into the array? If it's a bookmark it will contain
URIDictionary; if it's a folder it will contain
Title of the folder will be
com.apple.ReadingList. I needed to figure out how to specify an array element. With
PlistBuddy, the man page tells you what the commands are but not how to access elements. I eventually figured out that I can use
Children:3 to access element 3 of the
Children array. Here's a loop to go through the titles (assuming at most 10 bookmarks; you may need to increase this):
bookmarks_file="$HOME/Library/Safari/Bookmarks.plist" i=0 while [ $i -lt 10 ]; do title=$(/usr/libexec/PlistBuddy -c "print Children:$i:Title" $bookmarks_file 2>/dev/null) echo $i $title i=$[$i+1] done
The next step was to delete the folder that contains the Reading List. For some reason I can't remember, I used
plutil -remove instead of
PlistBuddy -c delete to delete the entry. But
plutil wants it written
Children.3 instead of
Children:3. Why? I don't know. The same loop as above, except when I find
com.apple.ReadingList I delete it:
bookmarks_file="$HOME/Library/Safari/Bookmarks.plist" i=0 while [ $i -lt 10 ]; do title=$(/usr/libexec/PlistBuddy -c "print Children:$i:Title" $bookmarks_file 2>/dev/null) if [ "$title" = "com.apple.ReadingList" ]; then plutil -remove "Children.$i" $bookmarks_file break fi i=$[$i+1] done
So now I can take the Reading List out of Safari and into JSON format. What to do from there? Pinboard is an obvious choice. I instead write the items out in a text file which I check periodically from Emacs.