Sigh⊠well you canât say I didnât try.
Canât wait!.
Sigh⊠well you canât say I didnât try.
Canât wait!.
It is a bit exciting, isnât it?
First of all, I reckon I have to code this as dirty as it need be. Should it prove to be faster to have 3-4 dangling lists, related to eachother by index, and removing items by 3-4 statements, without any handler calls, then so be it.
Iâll use this for figuring out if there are path names, or just the names in the title bars:
set pathinTitles to false
try
set pathinTitles to do shell script "defaults read com.apple.finder _FXShowPosixPathInTitle" as boolean
end try
Then there is the classification of windows, I am not sure about mounted volumes, the Finder Preferences window, or if info windows of files and folders show up as windows, or if they indeed are panels.
What I am sure of, is that every window in a space, are layered before any windows in any other space, so this time, the sole call to system events will be:
tell application id "sevs" to tell application process "Finder" to set finderWinCountCurSpace to count its windows
What to do with the superfluos windows obtained by
tell application id "MACS" to set allFinderWinCount to count its windows
Is something I havenât dealt with yet. Iâll figure something out.
(I believe I go faster through the Launch Services database by using creator code, than anything else.)
I am also going to put in some comment this time, but just a few.
I am also going to time alternative solutions during the weekend with getMillisec so you have to be patient. ![]()
Hello!
Joys script used 3, then 4 seconds, with the count dialog decoupled, mine did indeed use 5, then 5, Marks didnât run for some reason. 20 duplicate windows, 19 were closed, with a total of 59 windows open when the scripts were run.
Iâll just say that I do things with the targets of the finder windows, in order to have something to unique to work from that works in every situation. And that the script should be fairly robust, and work from whatever app.
Working with the targets of windows, and coercing finder references into aliases, must necessarily be a bit more expensive, than dealing with just text, but that is the only way you can assure that you have unique windows when you have, as the windows wonât be unique when using ânormalâ window titles, and two subfolders are carrying the same name.
It considers Finder windows only, so I donât deal with clippings windows, not knowing if it is possible to open duplicates of those anyway. But it do consider computer windows, and spotlight windows in current space.
Here it is, working so far, maybe Iâll try to optimize the loop further, and see if I can shave off more here. I doubt I can shave off more in the loops, but Iâll give it a try!
Edit
I am pondering adding the old part of my script as curtsey to those using posix paths in their window title, in the mean time, while I am pondering this, I have added a dialog, like a progress dialog, to show that something is indeed happening, leveraging on âignoring application responsesâ, to show users (me), that something are progressing.
Edit+
Added three comments.
script pruneDupFWins
-- © McUsr 2012 28.10.2012 completely rewritten to cope with all cases of window titles, and computer windows
property parent : AppleScript
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")
# COLLECTING NECESSARY DATA
# fastest way to make SystemEvents, get the window count for the windows appearing in the current space.
local fwc, clcount, prevApp # Finder Window Count, close count
set clount to 0
try
tell application id "sevs"
set prevApp to (name of every process whose frontmost is true and visible is true) as text
tell application process "Finder" to set fwc to count its windows
end tell
if fwc = 0 then return 0
on error
return 0 # Finder wasn't running!
end try
if fwc > 10 then
ignoring application responses
tell application id "com.apple.systemuiserver"
activate
try #
display dialog "Finding Duplicate Finder Windows in current space..." with title my scriptTitle buttons {"Ok"} default button 1 with icon my FinderIcon giving up after (fwc div 10)
end try
end tell
end ignoring
end if
# script for enhancing speed, not needed really
script o
property ides : {} # ides of wins
property targs : {} # targets
property tmpTargs : {} # third pair of tmp lists !
property tmpIdes : {}
end script
local startTargs, startIdes # firs pair of tmp lists for collecting
# collecting targets and ids of Finders windows, as fast as possible.
tell application id "MACS"
set {startTargs, startIdes} to {target, id} of its every Finder window
end tell
# PREPROCESSING OF FINDER-DATA BEFORE WE CAN LOOK FOR DUPLICATES
# we have to convert the Targets into text, The spotlight windows, just disappears in the process
# as we get a runtime error, «class ccmp» is a way to say computer-object outside a finder tell block.
local curtag, siftedTargs, siftedIdes # second pair of tmplists for sifting and preparing
set {o's targs, o's ides, siftedTargs, siftedIdes} to {startTargs, startIdes, {}, {}}
repeat with i from 1 to length of startTargs
try
set curTarg to item i of o's targs # curtag used for minimizing references
set end of siftedTargs to curTarg as alias -- as text
set end of siftedIdes to item i of o's ides
on error
try
if class of curTarg = «class ccmp» then
set end of siftedTargs to "Computer"
set end of siftedIdes to item i of o's ides
end if
end try
end try
end repeat
set {startTargs, startIdes} to {missing value, missing value}
# Finding the last finder window in our space, we have grabbed THEM all. Finder windows in other spaces
# has a higher index, than our last window number as obtained from system events.
local fwcAdj # Finder window count . Adjusted
set {o's ides, fwcAdj} to {siftedIdes, length of siftedIdes}
tell application id "MACS"
repeat
tell its Finder window id (item fwcAdj of o's ides) to if index of it > fwc then
set fwcAdj to fwcAdj - 1
else
exit repeat
end if
end repeat
end tell
set fwc to fwcAdj
# This count are the fwc first windows in our list we must consider for pruning duplicates of here.
# SIFTING OUT ANY DUPLICATE FINDER WINDOWS
set {o's ides, o's targs} to {items 1 thru fwc of siftedIdes, items 1 thru fwc of siftedTargs}
local tids, searchlist, idx, idList # used for having a searchlist, and the index for found elements
# idlist is the list of ids of finder windows we are going to close
set {tids, idList} to {AppleScript's text item delimiters, {}}
# What happens here, is that we take each line of the list of finder windows, chops it off the list
# and looks for duplicates, which corresponding id's are put onto the idlist for closure.
# we just churn thru the whole list until all duplicates are removed as fast as possible.
# if anybody has an idea of a faster way, I am all ears!
repeat
# this construct will fail when there are only one item left on the list.
try
set {searchItm, o's targs, o's ides} to {item 1 of o's targs, items 2 thru -1 of o's targs, items 2 thru -1 of o's ides}
set searchlist to o's targs
# an inlined handler indexofItem by Emmanuel Levy
set AppleScript's text item delimiters to return
set searchlist to return & searchlist & return
set AppleScript's text item delimiters to ""
try
set idx to -1 + (count (paragraphs of (text 1 thru (offset of (return & searchItm & return) in searchlist) of searchlist)))
on error
set idx to 0
end try
repeat while idx > 0
set end of idList to item idx of o's ides
if idx = 1 then
set {o's targs, o's ides} to {rest of o's targs, rest of o's ides}
else if idx = length of o's targs then
set {o's targs, o's ides} to {items 1 thru -2 of o's targs, items 1 thru -2 of o's ides}
else
set {o's targs, o's ides} to {items 1 thru (idx - 1) of o's targs & items (idx + 1) thru -1 of o's targs, items 1 thru (idx - 1) of o's ides & items (idx + 1) thru -1 of o's ides}
end if
set searchlist to o's targs
# an inlined handler indexofItem by Emmanuel Levy
set AppleScript's text item delimiters to return
set searchlist to return & searchlist & return
set AppleScript's text item delimiters to ""
try
set idx to -1 + (count (paragraphs of (text 1 thru (offset of (return & searchItm & return) in searchlist) of searchlist)))
on error
set idx to 0
end try
end repeat
on error
exit repeat
end try
end repeat
set AppleScript's text item delimiters to tids
# CLOSING ANY DUPLICATE FINDER WINDOWS
set clcount to length of idList
if clcount Ăąâ° 0 then
tell application id "MACS"
repeat with wid in idList
tell its Finder window id wid to close
end repeat
end tell
if clcount = 1 then
set msgText to "I closed 1 window!"
else
set msgText to "I closed " & clcount & " windows!"
end if
else
set msgText to "Nothing to do!"
end if
tell application id "MACS"
activate
try # comment out the line below when testing for speed
display dialog msgText with title my scriptTitle buttons {"Ok"} default button 1 with icon my FinderIcon giving up after 1.2
end try
end tell
tell application prevApp to activate
end script
# set t1 to (current date)
tell pruneDupFWins to run
(*
set t2 to (current date) - t1
tell application "Finder"
activate
display dialog "message " & t2
end tell
*)
It is fun. ![]()
I just realized I can make the script above run 2-3 seconds faster, by starting using names instead of targets. ![]()
Sifting out all computer windows, while I sift out spotlight windows.
And only comparing targets, when I look for duplicates, and finds a matching name.
Iâll come back with this, with a merged edition, that handles both posix pathnames, and regular folder names as windows title. Just like the script above, but this time, Iâll minimize the usage of targets of windows.
Now it uses no more than 3 seconds for both cases, with dialogs, 39 unique windows, 20 duplicates, no more than 2 seconds when the dialogs are removed.
It handles all cases for window titles with and without posix paths in them, Spotlight windows, Computer Windows, and identical window titles, when posix paths are not used.
Should anybody find bugs or anything, please let me know! ![]()
script pruneDupFWins
-- © McUsr 2012 28.10.2012 completely rewritten to cope with all cases of window titles, and computer windows
property parent : AppleScript
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")
# COLLECTING NECESSARY DATA
# fastest way to make SystemEvents, get the window count for the windows appearing in the current space.
local fwc, clcount, prevApp, pathInTitles # Finder Window Count, close count
set pathInTitles to false
try
set pathInTitles to (do shell script "defaults read com.apple.finder _FXShowPosixPathInTitle") as number as boolean
end try
try
tell application id "sevs"
if not (UI elements enabled) then set (UI elements enabled) to true (* to be sure than GUI scripting will be active Yvan Koenig*)
set prevApp to (name of every process whose frontmost is true and visible is true) as text
tell application process "Finder"
if visible of it is false then set visible of it to true
set fwc to count its windows
end tell
end tell
if fwc = 0 then return 0
on error
return 0 # Finder wasn't running!
end try
if fwc > 20 then
ignoring application responses
tell application id "com.apple.systemuiserver"
activate
try #
display dialog "Finding Duplicate Finder Windows in current space..." with title my scriptTitle buttons {"Ok"} default button 1 with icon my FinderIcon giving up after ((fwc div 10) - 1)
end try
end tell
end ignoring
end if
# COLLECTING THE FINDER WINDOWS
script o # script for enhancing speed, not needed really
property ides : {} # ides of wins
property targs : {} # targets
property tmpTargs : {} # third pair of tmp lists !
property tmpIdes : {}
end script
local startTargs, startIdes # first pair of tmp lists for collecting
tell application id "MACS" # collecting targets and ids of Finders windows, as fast as possible.
set {startTargs, startIdes} to {name, id} of its every Finder window
end tell
# PREPROCESSING OF FINDER-DATA BEFORE WE CAN LOOK FOR DUPLICATES
# Finding the last finder window in our space, we have grabbed THEM all. Possibly to many, if we have open
# file info windows and such in this space. Finder windows in other spaces has a higher index, than our
# window count as obtained from System Events.
local fwcAdj # Finder window count . Adjusted
set {o's ides, fwcAdj} to {items 1 thru fwc of startIdes, fwc}
tell application id "MACS"
repeat
tell its Finder window id (item fwcAdj of o's ides) to if index of it > fwc then
set fwcAdj to fwcAdj - 1
else
exit repeat
end if
end repeat
end tell
if fwcAdj = 0 then return 0
set {o's targs, o's ides} to {items 1 thru fwcAdj of startTargs, items 1 thru fwcAdj of startIdes}
if pathInTitles = true then
# Sifting out any computer windows.
# we have to convert the Targets into text, The spotlight windows, just disappears in the process
# as we get a runtime error, «class ccmp» is a way to say computer-object outside a finder tell block.
local curId, siftedTargs, siftedIdes, hadCompWin, curWinCount # second pair of tmplists for sifting and preparing
set {siftedTargs, siftedIdes, hadCompWin, curWinCount} to {{}, {}, false, fwcAdj}
repeat with i from 1 to fwcAdj
if (item i of o's targs) = "" then
set curWinCount to curWinCount - 1
try
set curId to item i of o's ides # curtag used for minimizing references
tell application id "MACS"
if class of (target of (its Finder window id curId)) = computer-object then
if hadCompWin = true then
close Finder window id curId
else
set hadCompWin to true
end if
end if
end tell
end try
else
set end of siftedTargs to item i of o's targs
set end of siftedIdes to item i of o's ides
end if
end repeat
set fwcAdj to curWinCount
if fwcAdj = 0 then return 0 # if there is nothing left, we'll leave the party!
set {o's ides, o's targs} to {siftedIdes, siftedTargs}
# set {startTargs, startIdes} to {missing value, missing value}
end if
# no point in the above if we are not showing posix paths in the titles, as then text will show up!
local searchTarg, searchIde, tids, searchlist, idx, idList, hadToSkip, skipList
# used for having a searchlist, and the index for found elements
# idlist is the list of ids of finder windows we are going to close
set {tids, idList} to {AppleScript's text item delimiters, {}}
repeat
# this construct will fail when there are only one item left on the list.
try
# start by removing blockers that we put on if we have to skip
set {searchTarg, searchIde, o's targs, o's ides} to {item 1 of o's targs, item 1 of o's ides, items 2 thru -1 of o's targs, items 2 thru -1 of o's ides}
set searchlist to o's targs
# an inlined handler indexofItem by Emmanuel Levy
set AppleScript's text item delimiters to return
set searchlist to return & searchlist & return
set AppleScript's text item delimiters to ""
try
set idx to -1 + (count (paragraphs of (text 1 thru (offset of (return & searchTarg & return) in searchlist) of searchlist)))
set {hadToSkip, skipList} to {false, {}}
on error
set idx to 0
end try
repeat while idx > 0
local dontSkipit
set dontSkipit to true
# todo: nÄr vi ikke har posix pathnames, sÄ sjekker vi targets her, om det er samme target.
# hvis det ikke er det, sÄ er index fortsatt ulik 0, sÄ vi fortsetter Ä sammenligne...
if pathInTitles = true then
set end of idList to item idx of o's ides
else
try
tell application id "MACS" to if (target of (Finder window id searchIde)) = (target of (Finder window id (item idx of o's ides))) then
set end of idList to item idx of o's ides
else
set {dontSkipit, hadToSkip, end of skipList} to {false, true, idx}
end if
on error
# spotlight windows
set {dontSkipit, hadToSkip, end of skipList} to {false, true, idx}
end try
end if
if dontSkipit then
if idx = 1 then
set {o's targs, o's ides} to {rest of o's targs, rest of o's ides}
else if idx = length of o's targs then
set {o's targs, o's ides} to {items 1 thru -2 of o's targs, items 1 thru -2 of o's ides}
else
set {o's targs, o's ides} to {items 1 thru (idx - 1) of o's targs & items (idx + 1) thru -1 of o's targs, items 1 thru (idx - 1) of o's ides & items (idx + 1) thru -1 of o's ides}
end if
else
# we must skip it, as the name isn't denoting the same folder, we should still continue searching for others though
set item idx of o's targs to "_@_" & item idx of o's targs
end if
set searchlist to o's targs
set AppleScript's text item delimiters to return
set searchlist to return & searchlist & return
set AppleScript's text item delimiters to ""
try
set idx to -1 + (count (paragraphs of (text 1 thru (offset of (return & searchTarg & return) in searchlist) of searchlist)))
on error
set idx to 0
end try
if idx = 0 and hadToSkip = true then # have to remove our trick before we commence
repeat with skippedWindow in skipList
local okTarg
set AppleScript's text item delimiters to "_@_"
set okTarg to text items of item skippedWindow of o's targs
set AppleScript's text item delimiters to ""
set item skippedWindow of o's targs to okTarg as text
end repeat
end if
end repeat
on error
exit repeat
end try
end repeat
set AppleScript's text item delimiters to tids
set clcount to length of idList
if clcount Ăąâ° 0 then
tell application id "MACS"
repeat with wid in idList
tell its Finder window id wid to close
end repeat
end tell
if clcount = 1 then
set msgText to "I closed 1 window!"
else
set msgText to "I closed " & clcount & " windows!"
end if
else
set msgText to "Nothing to do!"
end if
tell application id "MACS"
activate
try # comment out the line below when testing for speed
display dialog msgText with title my scriptTitle buttons {"Ok"} default button 1 with icon my FinderIcon giving up after 1.2
end try
end tell
tell application prevApp to activate
end script
tell pruneDupFWins to run
Hello!
Iâll just toss in this script to toggle posix paths in the title of Finder windows on and off
script FinderPosixPaths
set pathInTitles to false
try
set pathInTitles to (do shell script "defaults read com.apple.finder _FXShowPosixPathInTitle") as number as boolean
end try
if not pathInTitles then
do shell script "defaults write com.apple.finder _FXShowPosixPathInTitle -bool YES; killAll Finder"
else
do shell script "defaults write com.apple.finder _FXShowPosixPathInTitle -bool NO; killAll Finder"
end if
end script
tell FinderPosixPaths to run
The last script I posted runs fine on 10.6 and 10.8 it has no problem running on a standard Mac setup. !
The one think I did notice. Was anytime I messed with this command. My finder search would play up after. This included the contextual menu âShow in Finderâ. Not showing in finder And I could not type in Mission Control search field. Only a reboot would fix it. It may just be my system reacting this way ?.
Hello!
I am sorry to hear that the last one makes trouble for you, it runs fine for me under Mac OsX 106. The blog I found the foundation for it, also stated that it worked for Mac Os X 10.8 (Show Full Directory Path in Mac OS X Finder Window Title Bars)
As for your script, I ran it in the debugger, and it generates a run time error under 10.6 when posix path of finder windows titles are enabled, when it finds a spotlight window.
It maybe a 10.8+ thing. I have used the code before with now issue.
Have not tested the script with posix-names on 10.6. If I get a min I will.
Worked ok in 10.6 with posix-names. cannot test it in debugger as I do not have it.
By the way you may want to add a try-on error block for the do shell script code.
Like many of Apples prefs. The absence of a entry will be the same as an entry with 0,No,False.
This is the case with _FXShowPosixPathInTitle. It does not normally exist.
So your script will return an error of does not exist on Macs that have never run the defaults write com.apple.finder _FXShowPosixPathInTitle -bool YES code before.
Hello.
Now, that is entirely correct, that if a default value isnât set, then the do shell script will fail with an error.
I forgot that in the script above, but not in the script that closes duplicate windows.
Consider it fixed in the post above containing the script
Well, it didnât on my machine, you can just add a try block to avoid it. That is catching Spotlight windows, as their target will fail, the moment you check for a target, as the alias in targets of spotlight windows are invalid, when posix paths are shown in the finder window titles (phew). (The targets of them are specified as alias file ââ )
Edit
During the evening, Iâll post an updated version of the Finder window title script right here. As it is it makes you loose any Spotlight windows you have, which may not be convenient, if your queries are complex.
script FinderPosixPaths
# © McUsr 2012 and put in public domain! You are not allowed to post this elsewhere, nor in a publicly accessible repository
# please refer to it by this link: http://macscripter.net/edit.php?id=157144
property ScriptTitle : "ToggleFinderPosixPaths"
property FinderIcon : a reference to file ((path to library folder from system domain as text) & "CoreServices:Finder.app:Contents:Resources:Finder.icns")
on run
local pathInTitles, hasSpotlightWindows
set pathInTitles to false
try
set pathInTitles to (do shell script "defaults read com.apple.finder _FXShowPosixPathInTitle") as number as boolean
end try
set hasSpotlightWindows to false
# figuring out if we have any spotlight windows
script o # script for enhancing speed, not needed really
property ides : {} # ides of wins
property targs : {} # targets
end script
tell application id "MACS" # collecting targets and ids of Finders windows, as fast as possible.
set {o's targs, o's ides} to {name, id} of its every Finder window
repeat with i from 1 to length of o's ides
try
set a to target of (its Finder window id (item i of o's ides)) as text
# Just generating a run time error if there isn't a spotlight window, to signal that we got.
on error
if class of (target of (its Finder window id (item i of o's ides))) = computer-object then
else
set hasSpotlightWindows to true
end if
end try
end repeat
end tell
local theAnswer
if hasSpotlightWindows = true then
with timeout of 301 seconds
tell application "SystemUIServer"
activate
try
set theAnswer to button returned of (display dialog "You have finder Spotlight windows open. Do you want to loose them by restarting Finder?" with title my ScriptTitle buttons {"No", "Yes"} cancel button 1 default button 1 with icon my FinderIcon giving up after 300)
on error
set theAnswer to "No"
end try
end tell
end timeout
else
set theAnswer to "Yes"
end if
if theAnswer = "Yes" then
if not pathInTitles then
do shell script "defaults write com.apple.finder _FXShowPosixPathInTitle -bool YES; killAll Finder"
else
do shell script "defaults write com.apple.finder _FXShowPosixPathInTitle -bool NO; killAll Finder"
end if
end if
end run
end script
tell FinderPosixPaths to run
All Done! ![]()
Edit
Should computer-object be turned into (system-attribute -object), when you compile, then youâll have to enter «class ccmp» before compiling/saving.
That holds for both of my scripts.
Added a check for and promptly setting of UI Scripting enabled in my script in post #44 as it needs it to operate.
That was the hopefully very finishing touch!
Cool script!!
Thanks!
-Tim
Thank you. ![]()
Closes duplicate windows and skips Spotlight search windows.
This is about as terse as I can get it.
tell application "Finder"
set AppleScript's text item delimiters to linefeed
tell windows
if (get collapsed) contains true then set collapsed to false
set {winID, winTarg} to {id, paragraphs of (target as text)}
end tell
repeat with i from 1 to length of winTarg
set _win to item 1 of winTarg
set winTarg to rest of winTarg
if (_win is in winTarg) and (_win Ăąâ° "") then close window id (item i of winID)
end repeat
end tell
Hello.
Yes it is terse, and certainly look better than rather long and complex script I wrote, but my script is differnt in that it only deals with the windows in the current space, and that it does that as fast as possible.
Your script seems to be as fast as mine (if I remove the dialog code), or faster, but I have no time for timing, at the moment, fast enough will do.
But it is amazing, to see that you achieve what you do in so few lines. And maybe having windows unique in all spaces will do. I have not leveraged much upon the possibility of having the same window in several spaces.