MacOS – Applescript – how can I select all *non*-folders in an expanded list view window

applescriptfindermacos

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.

Best Answer

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)