2

I have made a very simple AppleScript to close tabs in Safari. The problem is, it works, but not completely. Only a couple of tabs are closed. Here's the code:

tell application "Safari"
    repeat with aWindow in windows
        repeat with aTab in tabs of aWindow
            if [some condition is encountered] then
                aTab close
            end if
        end repeat
    end repeat
end tell

I've also tried this script:

tell application "Safari"
    repeat with i from 0 to the number of items in windows
        set aWindow to item i of windows
        repeat with j from 0 to the number of tabs in aWindow
            set aTab to item j of tabs of aWindow
            if [some condition is encountered] then
                aTab close
            end if
        end repeat
    end repeat
end tell

... but it does not work either (same behavior).

I tried that on my system (MacBook Pro jan 2008), as well as on a Mac Pro G5 under Tiger and the script fails on both, albeit with a much less descriptive error on Tiger.

Running the script a few times closes a few tab each time until none is left, but always fails with the same error after closing a few tabs. Under Leopard I get an out of bounds error. Since I am using fast enumeration (not using "repeat from 0 to number of items in windows") I don't see how I can get an out of bounds error with this...

My goal is to use the Cocoa Scripting Bridge to close tabs in Safari from my Objective-C Cocoa application but the Scripting Bridge fails in the same manner. The non-deletable tabs show as NULL in the Xcode debugger, while the other tabs are valid objects from which I can get values back (such as their title). In fact I tried with the Scripting Bridge first then told myself why not try this directly in AppleScript and I was surprised to see the same results.

I must have a glaring omission or something in there... (seems like a bug in Safari AppleScript support to me... :S) I've used repeat loops and Obj-C 2.0 fast enumeration to iterate through collections before with zero problems, so I really don't see what's wrong here.

Anyone can help?

Thanks in advance!

Form
  • 1,949
  • 3
  • 25
  • 40

3 Answers3

7

I have a script that closes all of the tabs but does not need a repeat loop.

set closeTab to "Stack Overflow" as string
tell application "Safari"
    close (every tab of window 1 whose name is not equal to closeTab)
end tell

See if that works for you.

Note: change "Stack Overflow" to whatever the title name is of the tab you want to stay open.

  • That does indeed work and is a very interesting solution. Although I am going to use the Scripting Bridge in Cocoa I can't use this solution, I'm stuck with loops as far as I know. – Form Mar 24 '10 at 04:19
  • I don't see any reason why this shouldn't work in script bridge in fact I was planning on getting to this see my edit to come above – mcgrailm Mar 24 '10 at 12:12
  • well what I wanted to show you for some reason won't work so scratch that last comment about seeing the above edit – mcgrailm Mar 24 '10 at 13:52
  • Works in objc-appscript (http://appscript.sourceforge.net), e.g. `[[[[[[SFApplication applicationWithName: @"Safari"] windows] tabs] byTest: [[[SFIts name] contains: @"Stack Overflow"] NOT]] close] send]` – has Mar 24 '10 at 19:23
  • 1
    When I run this, it immediately throws an error saying "Safari got an error: Can’t get window 1 of window 1." What does this even mean? – user3932000 Jul 11 '16 at 16:28
5

this works for me nice and simple

  tell application "Safari"
    close every window
  end tell

ok you have to go from the count to 1 otherwise the count will be off when you close the window

  tell application "Safari"
    repeat with i from (count of windows) to 1 by -1
        repeat with j from (count of tabs of window i) to 1 by -1
            set thistab to tab j of window i
            set foo to name of thistab
            if foo is not equal to "bar" then close thistab
        end repeat
    end repeat
  end tell
mcgrailm
  • 17,469
  • 22
  • 83
  • 129
  • Yes... you're right this is a solution to close all tabs but I guess I didn't ask the right question. My goal is to conditionally close tabs based on their title, so I must iterate through the whole thing and compare the tabs' titles with an existing dictionary of words. – Form Mar 23 '10 at 20:37
  • There I modified my question. – Form Mar 23 '10 at 20:40
  • If I copy/paste the code you wrote it doesn't work, but the core of your suggestion is the answer: go from the count to 1 in reverse. Thanks! – Form Mar 24 '10 at 04:17
0

Both provided answers are fine, but I think it is better to combine both. This way you will be closing all tabs of all chrome windows, and it is less verbose than the first answer:

set closeTab to  "Post Attendee" as string
tell application "Google Chrome"
    repeat with i from (count of windows) to 1 by -1
          close (every tab of window i whose name is not equal to closeTab)
    end repeat
end tell
Danielo515
  • 5,996
  • 4
  • 32
  • 66