Industry guru Dave Taylor offers tech support on technical and business topics, including iPhone, iPod, Microsoft Windows, Sony PSP, cellphones, online advertising, CSS, Web design, business, Unix, Linux, SEO, Mac OS X, and shell script programming.     


Can I extract all my Safari bookmarks with a shell script?

Alright, this is pretty geeky, but is there a way I can grab all my Mac OS X Safari bookmarks using a shell script so I can manipulate the data? I've peeked into the bookmarks file and yow, it's one hairy data file!

Dave's Answer:

You're right. That's pretty darn geeky, especially when there are some very nice bookmark management tools available like BookmarkTool, URLManager Pro (which looks like the best of the bunch), and Bookit.

Further, if you use a little trick to turn on the Safari Debug menu, one of the options on that menu is ... ta da! ... Export Bookmarks.

How to enable the Safari Debug Menu: first off, quit Safari. Now, restart Safari because you actually need to copy the following before you quit (that's what happens when you're too eager!): defaults write com.apple.Safari IncludeDebugMenu 1. Now, quit Safari, then paste that command into the Terminal and restart Safari. You'll have a shiny new Debug menu available.

Alright, you ask, I deliver! It turns out that the Safari bookmarks are stored in an XML format file (as detailed in the question How do I keep my Safari bookmarks in sync?) which makes it a nightmare to parse and unwrap within the confines of a shell script.

The simplest is to just suck out all the URLs themselves, which can be done on the command line:

$ grep http: ~/Library/Safari/Bookmarks.plist
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" 
 "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  <string>http://www.coloradodaily.com/</string>
  <string>http://www.coloradodaily.com/</string>
  <string>http://news.google.com/</string>
  <string>http://news.google.com/</string>
  <string>http://www.nytimes.com/</string>
  <string>http://www.nytimes.com/</string>
  <string>http://online.wsj.com/home/us</string>
  etc, etc, etc
This isn't a particularly satisfying solution because of all the XML litter that comes along for the ride and the fact that each URL is duplicated.

Instead, a bit of analysis of the XML file itself reveals that it's the values URLstring and title that we're interested in, and that XML has the name, followed on the next line by the value. So here's a little magic:

$ bm="$HOME/Library/Safari/Bookmarks.plist"
$ grep -A1 -E '(>URLString<|>title<)' $bm |  
   grep -v -E '(>URLString|>title|^--)'
<string>CD</string>
<string>http://www.coloradodaily.com/</string>
<string>Gnews</string>
<string>http://news.google.com/</string>
<string>NYT</string>
<string>http://www.nytimes.com/</string>
<string>WSJ</string>
<string>http://online.wsj.com/home/us</string>
A huge improvement! Now to remove the tags so that it's just the data fields. There are a bunch of ways to do this ranging from cruelly hackish to slick and sophisticated. I'll opt for the former:
$ grep -A1 -E '(>URLString<|>title<)' $bm | 
  grep -v -E '(>URLString|>title|^--)' | 
  cut -d\> -f2 | cut -d\< -f1
CD
http://www.coloradodaily.com/
Gnews
http://news.google.com/
NYT
http://www.nytimes.com/
WSJ
http://online.wsj.com/home/us
Okay. That's 90% of the work. Let's just pour this into a shell script and use a while loop to read the information in the pipe, rewriting it as an attractive html href tag:
#!/bin/sh

# get Safari Bookmarks

bm="$HOME/Library/Safari/Bookmarks.plist"

grep -A1 -E '(>URLString<|>title<)' $bm | 
  grep -v -E '(>URLString|>title|^--)' | 
  cut -d\> -f2 | cut -d\< -f1 |
while read theTitle
do 
  read theUrl
  echo "<!-- $theTitle --><a href=\"$theUrl\">$theTitle</a><br />"
done | 
sort -f |
uniq

exit 0
You'll notice I've slapped a few refinements into the script, not the least of which is producing output that has the title of the link as a comment for sorting, and then using the sort -f | uniq pipe after the href's have been output to remove any dupes. If you'd rather not have anything sorted, just remove the sort -f ('-f' ignores case) and if you'd rather sort by the URL, just chop out the snippet in the echo statement that adds the title as an HTML comment.

Here's the output of running this script on my current bookmark file (well, part of it. Turns out I have a staggering 355 bookmarks). I have wrapped the text so as not to completely drive your Web browser insane trying to figure out how to render this page, but the output's the same:

$ get-safari-bookmarks.sh
<!-- .Mac --><a href="http://www.mac.com/">
.Mac</a><br />
<!-- 1-800-FLOWERS --><a href="http://www.1800flowers.com/">
1-800-FLOWERS</a><br />
<!-- 4D --><a href="http://www.4D.com/">
4D</a><br />
<!-- Aaron Faby's Mac OS X/Mac OS X Server Resources -->
<a href="http://www.aaronfaby.com/osx.shtml">
Aaron Faby's Mac OS X/Mac OS X Server Resources</a><br />
<!-- Aatrix --><a href="http://www.aatrix.com/">
Aatrix</a><br />
<!-- Activision --><a href="http://www.activision.com/">
Activision</a><br />
<!-- Adobe Systems --><a href="http://www.adobe.com/">
Adobe Systems</a><br />
<!-- AEC Software --><a href="http://www.aecsoft.com/">
AEC Software</a><br />
<!-- AJA Video Systems --><a href="http://www.aja.com/">
AJA Video Systems</a><br />
<!-- Aladdin Systems --><a href="http://www.aladdinsys.com/">
Aladdin Systems</a><br />
<!-- Amazon --><a href="http://www.amazon.com/">
Amazon</a><br />
etc etc
One last snippet. You can easily figure out how many bookmarks you have with this script too:
$ get-safari-bookmarks.sh | wc -l
355
Hope that's what you want. Ai yi yi. I'd rather just use the Safari Debug "Export Bookmarks..." feature, personally.

Related Shell Script Programming articles:
✔   Secretly capture screenshots on my Mac?
When I used to work on a Linux system, there was a utility we had that would let me take screen captures every...
✔   Parsing "id" strings in a Shell Script?
Hello Dave. I need a Bash shell script that creates a directories with the group names automatically when user logs in to the...
✔   Copy and Paste from the Mac OS X Command Line?
I am constantly running commands in Terminal.app on my MacBook and then copying and pasting the results into email messages or documents. Yes,...
✔   Script to test line lengths for Twitter compatibility?
I've been tasked with writing a series of tweets for a Black Friday marketing campaign and am finding it a bit tricky because...
✔   Shell script to convert lowercase to title case?
As part of a project I'm working on, I find myself deep in a Linux shell script, needing to have a subroutine that...

Let's stay in touch!
Sign up for my weekly AskDaveTaylor Newsletter and you'll receive even more tech and gadget help right to your inbox, along with exclusive news and industry updates. It's good stuff. I promise!
    Enter your name: and your email addr:  








Reader Comments To Date: 3

vel said, on August 29, 2006 11:47 PM:

good and thanx

Christopher said, on June 10, 2008 9:37 AM:

I do find that it is frustrating reading this stuff as you assume that EVERYONE os using Safari on a Mac. I am not. I love the Safari look and am using itg on a Windows XP Laptop (yeah, I can just about hear the cries of derision). I too find that Safari is a pig when it comes to organizing the bookmatks. It fact it is enough to put me off it. But I am persevering. Now onto my reason for writing all this. Is it possible for you to write how to organize bookmarks in Safari under Windows? I tried looking into the shell script thing, but realized that it would not work in my environment. And I do not want to get a third party program. Any ideas?

Babar said, on December 17, 2008 8:54 AM:

I am in the same situation as the fellow above, and am also seeking an answer. My Safari has stopped opening for some reason, so I downloaded Firefox and want to import my bookmarks. I'm on a Windows XP laptop, how do I do it? Thanks

Starbucks coffee cup I do have a lot to say, and questions of my own for that matter, but first I'd like to say thank you, Dave, for all your helpful information by buying you a cup of coffee!

I do have a comment, now that you mention it!











I will never send you any unsolicited email. Ever.






Check This Out Too...

 
Look for Answers
Need Help? Ask Dave Taylor!


Follow Me on Pinterest

Find Me on Google+
ADT on G+
© 2002 - 2013 by Dave Taylor. All Rights Reserved.

Note: This web site is for the purpose of disseminating information for educational purposes, free of charge, for the benefit of all visitors. We take great care to provide quality information. However, we do not guarantee, and accept no legal liability whatsoever arising from or connected to, the accuracy, reliability, currency or completeness of any material contained on this web site or on any linked site. Further, please note that by submitting a question or comment you're agreeing to my terms of service, which are: you relinquish any subsequent rights of ownership to your material by submitting it on this site. My lawyer says "Thanks".
"Ask Dave Taylor®" is a registered trademark of Intuitive Systems, LLC.