4

How can I get the POSIX path of the Finder window that is currently at the top of its window list? Preferably with some kind of Cocoa framework but I am open for anything.

Background: I would need this because I want to make a selection of files matching a regex pattern, starting recursively from this path. The idea is to use

[[NSWorkspace sharedWorkspace] subpathsAtPath:thePath]

method to get all the descendants of this path, use "grep" in an NSTask (to avoid packaging a regex support framework) and use

[[NSWorkspace sharedWorkspace] selectFile:aFile inFileViewerRootedAtPath:thePath]

in a loop looping through an NSArray made from the entries returned by grep.

So far, I have looked at NSWorkspace, NSFileManager and NSApplication plus other keyword searches within the Xcode Documentation.

Thanks for checking out my question!

Andre

PS: I am not sure about the grep part, maybe I'll just slap RegexKit Lite in there...

andreb
  • 596
  • 3
  • 16

4 Answers4

5

You can probably ask the Finder this via an AppleScript.

This* one-liner works for me:

osascript -e 'tell application "Finder" to set myname to POSIX path of (target of window 1 as alias)'

*a modified version of this.

Rhythmic Fistman
  • 34,352
  • 5
  • 87
  • 159
  • ah right... I totally forgot about AppleScript. Very nice to know that as a backup plan. Would you also happen to know a pointer or two to dealing with this in Cocoa/Carbon ? I wonder how http://www.manytricks.com/witch gets its listing of all the windows... thanks for writing this up :) – andreb Jun 26 '09 at 15:09
  • I don't know of a Cocoa/Carbon interface that lets examine the window list of another process. And even if you could, how would you determine what path it corresponded to? – Rhythmic Fistman Jun 26 '09 at 17:07
  • Thanks for this, this is exactly what I was after. I was missing the conversion to alias first. I tried to do things like "as POSIX path" instead of your "as alias" and "POSIX path of (target of window 1)" to no luck. It seems confusing to me that you first have to convert to an alias..! – James Bedford Aug 07 '12 at 18:25
3

I'm developing an commercial application that does exactly what you describe and I've been messing with different ways of doing this for over a year now. I'm a newbie developer, so I'm totally open to the idea that there may be a much better way of doing it than my way, but it seems to be stable and work.

I use Apple Script

I get the path of the active document every 3 seconds, but if the active application is the Finder, I get the path of the active window. I do this using Apple Script as described by the accepted answer.

Getting Window List using Carbon

To get the window list of all processes to get the window ID (something Apple Script can't do), I use CGWindowListCopyWindowInfo as detailed in this question:

Getting a unique ID for a window of another application

This presents me an array with all the windows of all processes ordered by which is frontmost. So all I need to do is pluck the first entry from the array. This can also be used to get a screengrab of the front window, if that's helpful to you, as shown in the Son of Grab sample application, which has been invaluable to me as a working example.

Sending Apple Script from Cocoa

When it comes to Apple Script, I've experimented with all 3 that Jim suggests and my conclusion is that each has it's issues, both in terms of stability and flexibility.

  1. Apple Event Manager relies on you sending raw Apple Events. For me, this was too much like hard work and too low level.

  2. Using NSAppleScript I found to be slow and error prone. It's also pretty clumsy when you want to send a whole variety of Apple Script messages as I do.

  3. When reading about Scripting Bridge, I got very excited, only to try it out and be very disappointed. For the attributes of the windows I was trying to grab, it didn't even recognise them as existing. It seemed to me to be buggy and weird. I expect if the commands you're sending are supported by SB, it would be the best option.

A Fourth Option

I now rely on a fabulous Objective C wrapper around Apple Script called AppScript. It's been around for many, many years, it's stable, the developer is great and most of all it just works.

It has rock solid methods which allow you to send Apple Script and it'll even return errors for you neatly without a whole load of potentially buggy and messy code needing to check for them.

I've been using it for a year now with no problems. If you have any other questions about how to do this, please don't hesitate to comment and I'll try my best to answer them.

Community
  • 1
  • 1
John Gallagher
  • 6,208
  • 6
  • 40
  • 75
  • Hey thanks for chiming in. Your explanations together with that nice sample code really go a long way. – andreb Oct 17 '09 at 02:01
  • No problems. If you've got any further questions, please don't hesitate to update this question. – John Gallagher Oct 17 '09 at 10:38
  • Hi John, Thanks for the Info. I tried SonOfGrab and it shows me a lot of "irrelevant" windows frontmost, like menu items and the like. How do you find out which window *really* is frontmost? – MrMage Jan 14 '11 at 22:46
  • There are a ton of different ways to do this depending on what you want to do and your limitations. I use AppScript and use the "AXFocusedWindow" or "AXMainWindow" of the frontmost process: `set theprocess to the first process whose frontmost is true` then `set thewindow to the value of attribute "AXFocusedWindow" of theprocess` or `set thewindow to the value of attribute "AXMainWindow" of theprocess` – John Gallagher Jan 17 '11 at 12:33
2

Getting the POSIX path represented by the frontmost window in the Finder is going to involve sending Apple Events to the Finder in one way or another.

Your choices include:

  • Using the Apple Event Manager (or NSAppleEventDescriptor and friends) directly.
  • Using NSAppleScript or OSAScript objects.
  • Using ScriptingBridge.

If you are building a Cocoa app, OSAScript is probably the most natural choice.

Jim Correia
  • 7,064
  • 1
  • 33
  • 24
  • Thanks for your reply, sir! A few names is already enough... will look into AEM/OSAScript. If it gets too complicated for my designer mind I will probably stick with the backup plan :D Again thanks to both of you. Your answers were helpful. Andre – andreb Jun 26 '09 at 16:08
2

It is possible get the POSIX path of the Finder's front window by using the ScriptingBridge with Swift

import Foundation
import ScriptingBridge // imports: ScriptingBridge.SBApplication, .SBElementArray, .SBObject

// SBApplication? to SBApplication to FinderApplication
let finder = (SBApplication(bundleIdentifier: "com.apple.finder")!) as FinderApplication
    
let windowList: SBElementArray = finder.windows!()
guard windowList.count > 0,
    let window = windowList[0] as? FinderWindow,
    let windowProperties = window.properties,
    let windowTarget = windowProperties["target"] as? FinderFolder,
    let windowUrlOptionalStr = windowTarget.URL,
    let windowUrlSubStr = windowUrlOptionalStr
        .removingPercentEncoding?
        .dropFirst(7) // "file://" 7 characters
else {
    // … handle failure
}

let windowUrl = URL(
    fileURLWithPath: String(windowUrlSubStr),
    isDirectory: true,
    relativeTo: nil)
marc-medley
  • 8,931
  • 5
  • 60
  • 66