i’ve no issues running my script for duplicate windows in application bundles too, as i do similar tests like you, always on the good old OS 10.6.
Check out if some of your osax-plugins or Script debugger interferes. Other Script editors may return different results as well, so i suggest to use the Applescript editor instead. Jo
I was just letting you know rather than wanting you to fix it.
To be honest I like the way my script works by getting rid of all the dupe windows in all the spaces.
Scripts like these risk being based on far too many variables related to individual Mac-User setup. We would be here for ever if we tried to accommodate them all.
As you say there is enough info here know for others to take the scripts in what ever direction they want.
FYI. Your script used 7 seconds, contra 2 seconds by mine, when both were executed from the scripts menu. My script where told to run, which I also did to your script, which made your script execute in 6 seconds.
I took all the trouble with my script for the speed.
And . I forgot to mention that: 1.2 seconds of the time of my script is used for showing a dialog within the test.
I also figured I’d test Mark Hunte’s script, although his script doesn’t quite fit the bill, as it operates on all spaces. I applied the same envelope script trick, to make it run faster before I ran it from the script menu, and alas it used 10 seconds, twice.
So much for what is necessary and not, in order to gain speed. 10 / 0.8 tells me that my script is 12,5 times faster than his. And that is where the complexity of the script stems from.
Hi McUsr,
sorry to disappoint you, but the speed factor isn’t related at the amount of code, but to the code structure one builds. Its not a novelty for me that putting scripts into a script-handler enhances the script execution dramatically. Then i get with my script 2 seconds for 33 duplicate windows, like you.
I write this not to have the last word, but to set the things right as they are.
You did, because I actually put your script inside a script, and told “joys” to run, with 30 unique windows, 20 duplicates, and then your script used 6 seconds. I started the timer after the dialog. and took the difference between that time, and the (current time) when your script was finished.
This is how your script looked when I ran the test, I ran the test twice, from the script menu, to be sure. It used 7 seconds both times. My script uses effectively 0.8 seconds, when we subtract the time it uses on showing the dialog. My script is 7 / 0.8 = 8.75 times faster than yours. (37 unique windows, 19 duplicates).
script joys
tell application "Finder" to set finder_icon to path to resource "Finder.icns"
try
set button_pressed to button returned of (display dialog "Close window Duplicates in." buttons {"Current Space only", "All Spaces", "Cancel"} default button 3 with icon finder_icon)
on error number the err
if err is -128 then return
end try
set t1 to (current date)
if button_pressed is "Current Space only" then
tell application "System Events" to set spaces_win to name of windows of process "Finder"
else
set spaces_win to 0
end if
tell application "Finder"
set {pt_ls, open_wins} to {{}, windows}
repeat with a in open_wins
if name of a does not end with "Clipping" then
set {the_id, the_pt} to {id, target} of a
set the_pt to (the_pt as text)
if the_pt is not in pt_ls then
copy the_pt to end of pt_ls
else
if spaces_win is 0 then
if the_pt is not "" then close a
else
if name of a is in spaces_win and the_pt is not "" then close a
end if
end if
end if
end repeat
set t2 to (current date)
activate
display dialog "" & (t2 - t1)
end tell
end script
tell joys to run
I am done with this now unless somebody has more to add.
The speed issue will also be different from Mac to Mac.
Your script does indeed run 2 seconds faster than mine on my Mac. (35 dupe windows) But I did not write it thinking about speed.
I only do that if the job it is going to do is intense. Which for me this task will never be. I will never have that many window open.
I could cut 2 seconds off mine. if I thought it important enough!, by changing all the individual calls to the target, id and name into a single call to properties.
Then just access the store of that.
set theProps to properties of this_item
set {windowID, windowTarget, windowName} to {id, target, name} of theProps (* get the windows target*)
and instead of closing each window with a call to finder for each. Just copy them to a list and close all of them at the end.
--close this_item (* close the Window *)
copy this_item to end of WindowClose
I have a hard time believing that our machines are that different. But people can try them, and see for them selves.
The script I posted, and which you dissicated in your blog, ( I write this here, since I haven’t been able to post a comment on your blog), was built for speed. Not for readability or any other thing.
Now, would you change the engine in a racing car, because it seems to complicated?
This is your script that I ran twice from the script menu yesterday, where it used 10 seconds each time.
As you can see I convoluted it before I ran it, since they tend to run faster then, so that the scripts would run under equal conditions.
script marks
set t1 to (current date)
set keepWindowList to {}
set closeWindowCount to 0
property scriptTitle : "Close Duplicate Windows"
property FinderIcon : a reference to file ((path to library folder from system domain as text) & "CoreServices:Finder.app:Contents:Resources:Finder.icns")
(* icon to use with end dialogue *)
tell application "Finder"
set theWindowList to every Finder window (* get the list of finder windows*)
repeat with i from 1 to number of items in theWindowList (* iterate through each winodow *)
set this_item to item i of theWindowList (* get a winodow in the list*)
set windowID to id of this_item (* get the windows unique id*)
set windowTarget to target of this_item (* get the windows target*)
set windowName to name of this_item (* get the windows name *)
if target of this_item is computer container then (* Check if window is a computer container *)
if windowName is in keepWindowList then (* Check if the window name is in the keepWindowList *)
set closeWindowCount to closeWindowCount + 1 (* add 1 to the closeWindowCount if the window name is in the list *)
close this_item (* close the Window *)
else
copy windowName to end of keepWindowList (* The Window name was not in the list so add it to the list*)
end if
else if windowName contains "Searching " then (* The Window was not a computer container so check if its a Search window*)
if windowName is in keepWindowList then (* Check if the window name is in the keepWindowList *)
set closeWindowCount to closeWindowCount + 1 (* add 1 to the closeWindowCount if the window name is in the list *)
close this_item (* close the Window *)
else
copy windowName to end of keepWindowList (* The Window name was not in the list so add it to the list*)
end if
else (* The Window was not a computer container or a Search window so it should be a normal finder window*)
set windowNTargets to POSIX path of (windowTarget as alias) (*Convert the target to an alias path from a file system item reference and then get its Posix path*)
if windowNTargets is in keepWindowList then (* Check if the window Target is in the keepWindowList *)
set closeWindowCount to closeWindowCount + 1 (* add 1 to the closeWindowCount if the window Target is in the list *)
close this_item (* close the Window *)
else
copy windowNTargets to end of keepWindowList (* The Window target was not in the list so add it to the list*)
end if
end if
end repeat
set t2 to (current date)
activate
display dialog "message " & t2 - t1
end tell
end script
tell marks to run
You posted a script which puzzled me at why it was so long and complex to the what appeared to be a simple task… Reading it was hard. I think it is fair to say I was not the only one who thought this.
So I wrote another script as an exercise for myself. And thought after, it would be good to put it up on the blog I was testing out.
But to do that. I had to give it some background on it. Which was your script and my reason I wrote mine. Also I did not want to make it look like the idea for the script came from me.
In the Blog I clearly say I intend you no disrespect in my lack of not understanding your script. And I feel I have not shown you any disrespect.
You have explained here what your intentions for your script were. And have asked me to update the blog. Which I have told you I will do.
I have also not disputed that your script is faster or any of you claims. And have tried to explain my point of view of what I want from such a script. It is clear we wrote the scripts with different intentions.
But you seem to have a bee in your bonnet about who’s script is faster and missing my point.
Mine was not built for speed. Because I will never need it to close more than a few windows. And it does what I wanted it to do which I have explained.
I do not care enough about it to have a protracted discussion about it that will clearly get us no where.
Please accept this fact and move on.
My point is, that I see my name on your blog, and that is so unfair. I am not sure if my comment to your blog reached you, as I had to make my own blog in order to post the comment.
The second point is, and this is the main point. Is that you can’t really compare the construction of two things built for two different purposes. Aka, the motor of a racing car, and make a different one, and claim that one to be better or anything, since it is simpler, and easier to understand.
All things said and done, I think I’ll have a second go on my script when time permits it, taking the “normal” naming of finder windows into account, and maybe tweaking its efficency further.
In the mean time, I’ll test the scripts for comparison on a machine with Mountain Lion, without SSD.
I cannot see your comments on the blog. It is new to me so I do not know why you cannot post a comment but it is set so people can post.!
I understand this. And that is why I said I will update the blog. My intention was not make you look bad. And I do not think the blog does that. But I will go over it.
script close_dups
tell application "System Events" to set spaces_win to name of windows of process "Finder"
tell application "Finder"
set {pt_ls, open_wins} to {{}, windows}
repeat with a in open_wins
if name of a is in spaces_win then
try
set {the_id, the_pt} to {id, target} of a
set the_pt to (the_pt as text)
if the_pt is not in pt_ls then
copy the_pt to end of pt_ls
else
if the_pt is not "" then close a
end if
end try
end if
end repeat
end tell
end script
set cu_dt to current date
tell close_dups to run
set f to (current date) - cu_dt
activate
display dialog f
.i thought we are here to learn something, only for this reason i continued to post. Let the battle be constructive.
Its a bit depressing to get lowered only because of a piece of code. We all want to improve but not at the cost to forget the common idea that should unite us.
Well, we are indeed here to learn something. I learn alot here, not always by Super Scripters, but there are always something to learn. It is a nice forum indeed, and I hope it stays that way.
I have now had the scripts run on an independent Mountain Lion machine, without SSD disk, here are the results:
mcUsrs : 1 then 1
joys : 4 then 4
Mark : 5 then 6 then 6 5I was surprised so I ran it one more time).
All scripts where inside a script-object, and executed from the script menu. Each with 20 duplicate windows.
To be perfectly clear about this, the structure,I am not sure what you mean by that, but efficency for me, is about how it will be executed on the machine. That is, you avoid uneccessary apple-events and such, and also does things the most efficient way.
My intention was never less code, nor more code, just the amount of code that made the script execute fast enough, but not faster. I believe I can cut the execution speed of my script in two, again.
This is kind of a bit to overwhelming discussion as I am aiming in two directions, addressing both you and Mark, for different reasons. I am not going to post a comment in Mark’s blog after all, this is quite enough.
@ Mark:
I usually put on copyright for scripts, when I care about them, so they don’t end up messed with. This time, at Macosxhints.com, I deliberately took that copyright notice away, since I wanted people to play with it. (When I have put a copyright notice on a script, then any kind of tinkering with it, without my permission is an infringement.) -But I somehow wanted them to play with it, and not for making it back into something I started off with, when I reckognized the need for speed. But for exploring how to achieve the speeds.
Now, how ironic isn’t that?
As for the critique of the failure to comment the script. I don’t believe in comments, I do believe in reading code, if I want people to take ownership of it. And you did indeed figure out that kList indeed meant keepList, didn’t you?
The other thing, which I tried to illustrate, with the racing car analogy, as it was the first that went through my mind, was that you can’t take a thing out of its proper context, and then rework it into something else, where it suddenly serves a different purpose. Now if I believed that, then I would have taken the original script I had, and blamed the original poster for it to not work fast enough.
So when both of you start to talk about to complicated, then you have to remember the context for it. Maybe I wasn’t that clear of it here. But it should have been easy to see over at macosxhints.com.
It was a failure of me that I didn’t mention the hack for getting full pathnames in the Finder windows, or that it wasn’t spelled out loud. I took about a month from I first submitted the hint, until it was accepted, so I guess it disappeared along the way.
As it stands now, I will rework the script to include both varieties of finder windows, and consider the clippings and computer window, and tweak out the rest of the speed. Hopefully I will manage to do this during the weekend.
As it stands, I am done with this subject. (As soon as Mark has changed his blog.)
Hi,
(.) canceled because i want to rest in peace with the world.
Most of the time i do not complete my scripts i post, because i need to understand only parts of a bigger whole i code and want to learn how to fill in my gaps. McUsr,
Have you even tried to run the last script i posted ? i changed some very small things to get same results with my script within a different script structure: 2 seconds for 33 finder windows, with 2-4 different duplicates for each window.
I agree with you, that apple events and sorting routines are important, WHEN tasks become longer and complexer.
Nobody is perfect, as we all need to learn DIFFERENT lessons, and that’s the essence of being a member of a forum, in my eyes.
I hope we can close this thread now.
Last but not least, it makes me sad to think that i started this thread for fun.
I didn’t, and I won’t, I used the version you said was only 2 seconds slower. And I am done with this.
if you want to perform further tests, feel free to do so.
I will on the other hand test it when I have my final more versatile is version done.
For what it is worth: I have discovered, that text item delimiters, combined with paragraphs, is indeed a very fast way to find, and position items. My script is based around Nigel’s handler which I named getSingleton, since his name for it, was waayyy to long and laborious to type. (Sorry about that! :D). So I am a copyright violator!
I want to say a little bit more about my script while I am at it.
During the past months I think my insight has grown. I have done some interesting findings, concerning text and lists. Those findings put sorting, and looking up into a whole new light when it comes to AS. As it looks like sorting would only be needed when representing the data is necessary. Text item delimiters and the paragraphs, and coercing from lists to text and back again, has so far, proved to me, to be far more efficient, than sorting data before looking them up, returning index positions and so on. This puts some constraints on the data, regarding uniqueness and so on. I have to delete items, in order to get to the next. It is still very fast.
This won’t work in all cases, like with records I think, because the coercion back and forth between text is to expensive.
This handler has been further optimized than me, and posted elsewhere here, and works for sublists with 3 and 4 items in it, and so far it seems like a faster way to get things returned, than using the is in construct for returning sublists, with the same constraints regarding the uniqueness of the items in the list. I just thought I’d share that.
And I am in a good mood, just saying, no hard feelings at all.
Ok, that sounds better. Nobody in this thread/ our forum should feel degraded. We are all here because we have very similar interests.
As i said already at the very beginning of this thread, McUsr, that your script is technically interesting.
We have to help and support each other even when we fail, to be a community, AND we have to show our assetions in examples where others lack and commit errors. Words alone are misleading, often.
We all have principles, not? I like short scripts, for example.
I did another investigation (see script below) and got this result: 4 sec x 60 duplicate windows x current space (current space is an optional, and its easy to remove, to extend the search to all spaces)
tell me what you think about this:
script close_dups
tell application "System Events" to set spaces_win to name of windows of process "Finder" whose name does not end with "Clipping"
tell application "Finder" to set {compcont, startup_d} to {name of computer container, name of startup disk}
set {uniq_ls, dupl_ls} to {{}, {}}
repeat with a in spaces_win
if a is not startup_d then
set nm_win to a as text
else
set nm_win to compcont as text
end if
if nm_win is not in uniq_ls then
copy nm_win to end of uniq_ls
else
copy nm_win to end of dupl_ls
end if
end repeat
set c_dups to count items in dupl_ls
set {uniq_ls, dupl_ls2} to {{}, {}}
tell application "Finder"
set the_pt to windows
repeat with a in the_pt
set nm to name of a
if nm is in dupl_ls or nm is compcont then
if nm is compcont then
set get_loco to compcont
else
if target of a is not "" then
set get_loco to target of a as text
end if
end if
if get_loco is not in uniq_ls then
copy get_loco to end of uniq_ls
else
copy a to end of dupl_ls2
end if
end if
end repeat
if dupl_ls2 is not {} then close dupl_ls2
end tell
activate
display dialog ("closed " & c_dups & " duplicate windows" as text)
end script
set cu_dt to current date
tell close_dups to run
set f to (current date) - cu_dt
activate
display dialog ("Speed: " & f & " seconds" as text)
McUsr. The blog is updated to take into discussion here :).
Also for posterity the last code I wrote.
set keepWindowList to {}
set WindowClose to {}
tell application "Finder"
set theWindowList to every Finder window (* get the list of finder windows*)
repeat with i from 1 to number of items in theWindowList (* iterate through each winodow *)
set this_item to item i of theWindowList (* get a winodow in the list*)
set theProps to properties of this_item
set {windowID, windowTarget, windowName} to {id, target, name} of theProps (* get the windows target*)
if windowTarget is computer container then (* Check if window is a computer container *)
if windowName is in keepWindowList then (* Check if the window name is in the keepWindowList *)
copy this_item to end of WindowClose
else
copy windowName to end of keepWindowList (* The Window name was not in the list so add it to the list*)
end if
else if windowName contains "Searching " then (* The Window was not a computer container so check if its a Search window*)
if windowName is in keepWindowList then (* Check if the window name is in the keepWindowList *)
copy this_item to end of WindowClose (* add it to the WindowClose list*)
else
copy windowName to end of keepWindowList (* The Window name was not in the list so add it to the list*)
end if
else (* The Window was not a computer container or a Search window so it should be a normal finder window*)
set windowNTargets to POSIX path of (windowTarget as alias) (*Convert the target to an alias path from a file system item reference and then get its Posix path*)
if windowNTargets is in keepWindowList then (* Check if the window Target is in the keepWindowList *)
copy this_item to end of WindowClose (* add it to the WindowClose list*)
else
copy windowNTargets to end of keepWindowList (* The Window target was not in the list so add it to the list*)
end if
end if
end repeat
close items of WindowClose (* Close all the items/windows in the WindowClose list*)
end tell