Saving browser tab sets

I often find myself in the middle of some online research with several browser tabs open. I need to stop and move on to something else, but I want to be able to return to my current browser state a day or two from now. I’m going to be using the browser for other things in the meantime, so I can’t just flip the setting that allows me to quit and then relaunch to the same state.

Safari launch preference

There are a few options for saving the browser state, and unsurprisingly, I’ve chosen one that involves scripting. But let’s look over a few others, too.

Pinboard tab sets

First, there’s the remote solution. Pinboard has a Save Tab Sets extension1 that allows you to create a set of bookmarks from all your open tabs that can be accessed through a single name.

Pinboard tab set

Days later, when you want to return to the previous state, go to Pinboard, choose that tab set, and open all the bookmarks.

Open saved tab set in Pinboard

This is a quick, clean solution, but I’m starting to favor local storage instead of the cloud, and it’s often very nice to have all the research links for a project stored with all my other work in the project folder. I’m sure there’s a way to export these links from Pinboard into an OPML file that could be saved to the project folder, but that complicates what should be a simple process. Let’s look at something else.

Safari and Chrome bookmark folders

A simple local solution in Safari is to choose the Add Bookmarks for These n Tabs… command from the Bookmarks menu.

Save tabs as bookmarks in Safari

Chrome has a similar Bookmark All Tabs… command.

Both of these commands create a folder with bookmarks to every tab. All the bookmarks can be opened at a later date with a single menu selection.

Open folder of tabs in Safari

This doesn’t store the bookmarks in the project folder, but that can be done by choosing the Show All Bookmarks command (or clicking the little book icon in the bookmarks bar) and dragging the folder of links from the Safari window into the project folder. That creates a folder of .webloc files that can be double-clicked to open the web pages. At some point, it’ll be necessary to go back and delete these bookmarks from Safari to keep the Bookmarks menu clean.

Bookmarks window in Safari

What I don’t like about this solution—apart from the need to clean up the Bookmarks menu—is that .webloc files aren’t just plain text. It’s not especially hard to extract the plain text URLs from them (they can, for example, be dragged into a text file), but I’d rather they be stored in a more universal format.

Oddly enough, dragging a folder of bookmarks from Chrome into the Finder creates a single .textclipping file with all the URLs. This can be dragged into a text file, which is nice, but won’t open the web pages when double-clicked.

Scripts that write scripts are the luckiest scripts in the world

Which leads to my little AppleScript, “Save Tabset.” It creates an executable bash script file that looks like this:

bash:
#!/bin/bash

open -g http://hints.macworld.com/article.php?story=20100112100027790
open -g http://www.chipwreck.de/blog/
open -g http://daringfireball.net/2004/02/setting_empty_file_and_creator_types
open -g http://www.google.com/search?client=safari&rls=en&q=pinboard+save+tab+sets&ie=UTF-8&oe=UTF-8
open -g http://www.flickr.com/photos/drdrang/8117740799/

The URLs are all there in plain text, and when the file is double-clicked, it launches Terminal (which I always have running anyway) and opens all the web pages in the default browser.

When invoked, which I do through FastScripts, “Save Tabset” puts up the standard save file dialog box, which allows the user to save the shell script with any name in any folder. As a first guess, it assumes you want the script saved in the folder of the frontmost Finder window.

Save Tabset

Here’s the AppleScript:

applescript:
 1:  -- Assume the frontmost Finder window (or the Desktop)
 2:  -- is where we want to store the script.
 3:  try
 4:    tell application "Finder" to set defaultFolder to the folder of the front window
 5:  on error
 6:    set defaultFolder to (path to desktop)
 7:  end try
 8:  
 9:  -- Initialize the text ot the script.
10:  set cmd to "#!/bin/bash" & linefeed & linefeed
11:  
12:  -- Add commands to open all the tabs.
13:  tell application "Safari"
14:    set n to count of tabs in front window
15:    repeat with i from 1 to n
16:      set cmd to cmd & "open -g " & URL of tab i of front window & linefeed
17:    end repeat
18:  end tell
19:  
20:  -- Open/create a file and save the script.
21:  set scriptAlias to choose file name default name "tabset" default location (defaultFolder as alias)
22:  set scriptPath to POSIX path of scriptAlias
23:  set scriptFile to open for access scriptAlias with write permission
24:  set eof scriptFile to 0
25:  write cmd to scriptFile starting at eof
26:  close access scriptFile
27:  
28:  -- Change the file attributes to make it double-clickable.
29:  do shell script "chmod 777 " & scriptPath
30:  do shell script "xattr -wx com.apple.FinderInfo '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00' " & scriptPath

Lines 1-7 set the default folder for saving the tabset script—the frontmost Finder window if there is one and the Desktop if there isn’t. Nothing precludes the user from changing the folder when the dialog appears.

Lines 9-18 generate the text of the tabset script by cycling through the tabs of the frontmost Safari window and adding an open -g <url> line for each one. When the tabset script is run, the -g option tells the open command not to bring the browser to the foreground. This makes it easier to dismiss the Terminal window that appears with the tabset script is double-clicked. If you’re a Chrome user, just change Line 13 to

applescript:
13:  tell application "Google Chrome"

Lines 20-26 open a file and write the script out to it.

Lines 28-30 are, admittedly, weird. Line 29 makes the tabset script universally readable, writable, and executable. Line 30 sets both the file type and file creator to null. Both of these are necessary for the script to be taken as a Unix Executable File that gets opened and run in the Terminal when double-clicked. (This may be a Lion-related bug; I still haven’t upgraded to Mountain Lion.)

You may be wondering why I don’t use the AppleScript commands set file type and set file creator, as John Gruber showed in this Daring Fireball post from way back in ’04. The reason is they don’t work. I don’t know why they don’t work, but I tried and they don’t. I found the xattr solution in this Mac OS X Hint. That’s 32 pairs of zeros between the single quotes.

With this AppleScript, I get a single command that does everything I want:


  1. The tab set feature is also included in the Pinbar extension, but I don’t like the Pinbar, because it adds another toolbar across my browser window.