2

I am trying to write a script which will select all non-folders in a given Finder window which is in List View and has revealed/expanded all sub-folders (see image).

As there tend to be many more files than folders, my thought is to:

  1. Select all items
  2. Deselect all folders

I am also willing to start with nothing selected and then add non-folders to my selection.

In any case, I'm stumped. Any help would be appreciated.

Desired result would look similar to this:

enter image description here

EDIT: (to answer the xy problem - it's gonna be long, but you asked for it)

I repair computers for a living, which means I do a lot of "Backup data, erase hard disk, install OS, restore data" all the time. Both Windows and Mac, although I do all the backups on my Mac, so the client's data is restored from a Mac volume via the network.

Usually, I just drag entire folders from backup volume to restored Windows PC and wait for it to finish. Sometimes, though, the copy fails, often because "the pathname is too long" or some such nonsense. In such cases, I end up copying smaller chunks at a time until I'm done.

Then I have to check and double check that I haven't missed any files/folders. So, I open two windows, one with the source folder, the other with the destination folder. And I compare folders (Music, Docs, etc.) from each. I look to see if the number of files/folders match and that the amount of bytes used is the same.

Often, because of the .DS_Store in Mac folders, the bytes don't match. If I open the folder and Get Summary Info on just the contents, the byte counts match up perfectly.

So, rather than open dozens or hundreds of folders and subfolders, one by one, what I do is open the Documents folder, for example, in list view, reveal all subfolders (this much I can do in AppleScript already) and then I Select All and de-select the folders, and then Get Summary Info.

In my image above, I could do it manually, of course. But, in many cases, I have folders with hundreds of files and several folders deep. If I do it manually, it takes a long time and inevitably, right before deselecting the last 10 folders, I'll make an errant click and have to start all over.

This is why I want a script to select all non-folders.

If there is another solution, great. Let me hear it.

4
  • Why do you want to select them? If you tell the problem, perhaps there is a better solution. Read this XY Problem.
    – user14492
    Commented Dec 7, 2015 at 16:14
  • 1
    this use case doesn't need a GUI, and seems better suited to a product designed to synchronize filesystems: rsync.
    – Tim B
    Commented Dec 7, 2015 at 21:48
  • I'm with @TimB you should look into rsync to do these backups. If you use it correctly if/when a backup gets interrupted it will intelligently examine the successfully copied files, ignore them and essentially resume the backup of just the ones that were missed. One thing to note is if you are copying from Windows to Mac the two filesystems (NTFS and HFS+ respectively) store timestamps differently. So look into the --modify-window switch or it can end up copying everything every time. :) Commented Dec 8, 2015 at 1:18
  • 1
    I've just spent 3 hours trying to get rsync working. Mac->Windows using cygwin failed for various reasons. Acrosync/Win is creating duplicates of the folders which were already copied and verified, due to file/folder-names with accents. In short, this "answer" is not helping much at the moment. I will continue on investigating this tool for the future, but could someone please answer the question I asked instead of suggesting something else entirely? If I "select all" in my image above before running the script, is there a way to put the selection into a variable that I can traverse? Commented Dec 8, 2015 at 11:53

2 Answers 2

1

If all folders are expended in the list view , here are two solutions.

First solution:

This AppleScript

my deselectAllFolders()

on deselectAllFolders()
    script o
        property sel : {}
    end script
    tell application "Finder"
        set o's sel to selection as alias list
        set tc to count o's sel
        repeat with i from 1 to tc
            if class of item (item i of o's sel) is folder then set item i of o's sel to missing value
        end repeat
        set selection to aliases of o's sel -- select all items without folders
    end tell
    return "" -- to not put all files into the result (it's very slow to show an huge list in the editor )
end deselectAllFolders

Cons:

  • All items must be selected before executing the script.
  • Slow on huge list of items.

Second solution:

This AppleScript

set pScript to "from Foundation import NSFileManager, NSURL, NSDirectoryEnumerationSkipsHiddenFiles, NSURLIsDirectoryKey, NSURLIsPackageKey; from ScriptingBridge import SBApplication
def procFolder(fold):
    p = df.contentsOfDirectoryAtURL_includingPropertiesForKeys_options_error_(fold, [NSURLIsDirectoryKey, NSURLIsPackageKey], NSDirectoryEnumerationSkipsHiddenFiles, None)[0]
    for f in p:
           r=f.getResourceValue_forKey_error_(None, NSURLIsPackageKey, None)
           if r[0] and r[1]:
               allFiles.append(f)
           else:
               r=f.getResourceValue_forKey_error_(None, NSURLIsDirectoryKey, None)
               if r[0] and r[1]:
                     procFolder(f)
               else:
                     allFiles.append(f) 

allFiles = []
df=NSFileManager.defaultManager() 
finderApp = SBApplication.applicationWithBundleIdentifier_(\"com.apple.finder\")
tPath = finderApp.FinderWindows()[0].target().get()
procFolder(NSURL.URLWithString_(tPath.URL()))
finderApp.setSelection_(allFiles)"

do shell script "/usr/bin/python -c " & quoted form of pScript
  • No need to select all the items in the list view.
  • Fast (1.5 second on 8500 items)
2
  • Please note that with macOS 12.3, /usr/bin/python no longer exists, and you should use /usr/bin/python3 instead. Also, you will need to install the PyObjC wrapper before running this script with /usr/bin/pip3 install pyobjc.
    – juandesant
    Commented Mar 18, 2022 at 21:01
  • Also, it does not work if the folders containing further documents are not disclosed… For a hierarchy of files, you need to be in List view, and all relevant folders need to have their disclose triangle open.
    – juandesant
    Commented Mar 21, 2022 at 11:15
0

Unfortunately, Finder doesn't support revealing files in this way.

The following code sets 'theFiles' to the files in the directory chosen, but 'reveal' doesn't support any parameters. If you already have the window open, it selects the files in the root of the chosen folder in that window, but then opens a window for every other folder recursively.

tell application "Finder"
  set theFiles to get every item of (entire contents of folder (choose folder)) whose kind ≠ "Folder"
  reveal theFiles
end tell

I still feel like this is more of an XY problem though.

2
  • yeah, I still haven't found the correct word to use, as "reveal" seems to have a different meaning. My script already changes the front window of Finder to List View, selects all the folders, and then issues the "Option-Right Arrow" keystroke to expand all folders and their subfolders. What baffles me is why I can't then issue "Select All" in the script whereas manually, I can. I feel like if I could just get the "Select All" to work, I could save the selection to a variable, and then cycle through it to remove the non-folder items. Anyways, any help is appreciated. Commented Dec 7, 2015 at 20:17
  • @Zonker Oh, GUI scripting, I hadn't even thought of that approach. I went straight for the Finder AppleScript dictionary to try to obtain the list of files programmatically, then reveal them. I'd still say AppleScript isn't the right approach and Keyboard Maestro has much better scripting (both GUI and programmatically), even if this feels like an XY problem. I look forward to seeing an alternative solution.
    – grg
    Commented Dec 7, 2015 at 20:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .