Apple Event: May 7th at 7 am PT

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Automator Quickaction "File Count" in folders and subfolders

I found a quickaction here Why does Apple count the folder as 1 when… - Apple Community

Unfortunately this works with one folder only.


I need a similar script to count the files in folders and all its subfolders.

Can somebody help ?

iMac 27″, macOS 13.0

Posted on Dec 12, 2022 8:46 AM

Reply
Question marked as Best reply

Posted on Dec 14, 2022 1:45 PM

Ok. I rewrote this Quick Action to recursively descend from a starting folder selection and return the file count found in the hierarchy. I tested with one file in a 10-deep folder hierarchy and it got that correctly, and then a deeper hierarchy and it got that file count correctly too. Tested: Ventura 13.1.


It is no longer a Run Shell Script and for speed, does not use the Finder. Here is the code for the Run AppleScript Quick Action:


Code:

use framework "Foundation"
use AppleScript version "2.4" -- Yosemite or later
use scripting additions

property NSString : a reference to current application's NSString
property NSURL : a reference to current application's NSURL
property NSArray : a reference to current application's NSArray
property NSFileManager : a reference to current application's NSFileManager
property NSDirectoryEnumerationSkipsHiddenFiles : a reference to current application's NSDirectoryEnumerationSkipsHiddenFiles
property NSDirectoryEnumerationSkipsPackageDescendants : a reference to current application's NSDirectoryEnumerationSkipsPackageDescendants
property NSURLIsRegularKey : a reference to current application's NSURLIsRegularKey
property NSURLIsRegularFileKey : a reference to current application's NSURLIsRegularFileKey

on run {input, parameters}
	
	if (count of input) = 0 then return
	
	set thisItem to (POSIX path of input) as text
	set tildeFolder to ((NSString's stringWithString:thisItem)'s stringByAbbreviatingWithTildeInPath) as text
	display dialog "Folder:  " & tildeFolder & return & "Files:" & tab & (my hierarchyFileCount(thisItem)) as text ¬
		with title "File Count for Folder Hierarchy"
	return
end run

on hierarchyFileCount(infolder)
	-- beginning with a folder, recurse downward and get just filenames and their count
	-- It ignores dot files, foldernames, and Apple Package folders
	set dirURL to NSURL's fileURLWithPath:infolder
	set enumOptions to (NSDirectoryEnumerationSkipsPackageDescendants as integer) + (NSDirectoryEnumerationSkipsHiddenFiles as integer)
	
	set fileArray to NSArray's array()'s mutableCopy()
	set fm to NSFileManager's defaultManager()
	
	set dirEnumerator to fm's enumeratorAtURL:dirURL includingPropertiesForKeys:{} options:enumOptions errorHandler:(missing value)
	
	repeat with afileRef in dirEnumerator's allObjects()
		set {result, isFile} to (afileRef's getResourceValue:(reference) forKey:NSURLIsRegularFileKey |error|:0)
		if (isFile's boolValue()) = true then
			(fileArray's addObject:(afileRef's valueForKey:"path"))
		end if
	end repeat
	
	return (fileArray's |count|()) as integer
end hierarchyFileCount


13 replies
Question marked as Best reply

Dec 14, 2022 1:45 PM in response to macsuperuser

Ok. I rewrote this Quick Action to recursively descend from a starting folder selection and return the file count found in the hierarchy. I tested with one file in a 10-deep folder hierarchy and it got that correctly, and then a deeper hierarchy and it got that file count correctly too. Tested: Ventura 13.1.


It is no longer a Run Shell Script and for speed, does not use the Finder. Here is the code for the Run AppleScript Quick Action:


Code:

use framework "Foundation"
use AppleScript version "2.4" -- Yosemite or later
use scripting additions

property NSString : a reference to current application's NSString
property NSURL : a reference to current application's NSURL
property NSArray : a reference to current application's NSArray
property NSFileManager : a reference to current application's NSFileManager
property NSDirectoryEnumerationSkipsHiddenFiles : a reference to current application's NSDirectoryEnumerationSkipsHiddenFiles
property NSDirectoryEnumerationSkipsPackageDescendants : a reference to current application's NSDirectoryEnumerationSkipsPackageDescendants
property NSURLIsRegularKey : a reference to current application's NSURLIsRegularKey
property NSURLIsRegularFileKey : a reference to current application's NSURLIsRegularFileKey

on run {input, parameters}
	
	if (count of input) = 0 then return
	
	set thisItem to (POSIX path of input) as text
	set tildeFolder to ((NSString's stringWithString:thisItem)'s stringByAbbreviatingWithTildeInPath) as text
	display dialog "Folder:  " & tildeFolder & return & "Files:" & tab & (my hierarchyFileCount(thisItem)) as text ¬
		with title "File Count for Folder Hierarchy"
	return
end run

on hierarchyFileCount(infolder)
	-- beginning with a folder, recurse downward and get just filenames and their count
	-- It ignores dot files, foldernames, and Apple Package folders
	set dirURL to NSURL's fileURLWithPath:infolder
	set enumOptions to (NSDirectoryEnumerationSkipsPackageDescendants as integer) + (NSDirectoryEnumerationSkipsHiddenFiles as integer)
	
	set fileArray to NSArray's array()'s mutableCopy()
	set fm to NSFileManager's defaultManager()
	
	set dirEnumerator to fm's enumeratorAtURL:dirURL includingPropertiesForKeys:{} options:enumOptions errorHandler:(missing value)
	
	repeat with afileRef in dirEnumerator's allObjects()
		set {result, isFile} to (afileRef's getResourceValue:(reference) forKey:NSURLIsRegularFileKey |error|:0)
		if (isFile's boolValue()) = true then
			(fileArray's addObject:(afileRef's valueForKey:"path"))
		end if
	end repeat
	
	return (fileArray's |count|()) as integer
end hierarchyFileCount


Dec 19, 2022 6:22 AM in response to macsuperuser

Based on the bug that I uncovered in the Run AppleScript action's compiler, I made two decisions.

  1. Count the occurrence of any package folder without counting the contents within it
  2. Provide a working Zsh script that just takes a folder path, and uses improvements to the AppleScript


This provides the familiar result display dialog as I have shown previously. Implement the following code in an Automator Quick Action Run Shell Script action as I shared previously in this thread and it will drill down into the selected hierarchy with the intended result.


Code:


#!/bin/zsh

(( $# )) || { /usr/bin/osascript -e 'display dialog "No folder selection… quitting."';exit 1}

STARTDIR="${1:a:s/\~\//}"

function hierarchyFileCount () {
    /usr/bin/osascript <<AS

    use framework "Foundation"
    use framework "AppKit"
    use AppleScript version "2.4"
    use scripting additions

    property ca : current application

    set dirURL to ca's NSURL's fileURLWithPath:"${1}"
    set enumOptions to (ca's NSDirectoryEnumerationSkipsPackageDescendants as integer) + ¬
                       (ca's NSDirectoryEnumerationSkipsHiddenFiles as integer)
    set fileArray to ca's NSArray's array()'s mutableCopy()
    set fm to ca's NSFileManager's defaultManager()
    set nsws to ca's NSWorkspace's sharedWorkspace()

    # recursively descend into folder hierarchy
    set dirEnumerator to fm's enumeratorAtURL:dirURL includingPropertiesForKeys:{} ¬
                              options:enumOptions errorHandler:(missing value)

    repeat with afileRef in dirEnumerator's allObjects()
        set {result, isFile} to afileRef's getResourceValue:(reference) ¬
                                forKey:ca's NSURLIsRegularFileKey |error|:(missing value)

        # count only regular files and occurrence of package folder items
        if (isFile's boolValue()) = true or ((nsws's isFilePackageAtPath: ¬
                                             (afileRef's valueForKey:"path"))) = true then
           fileArray's addObject:afileRef
        end if
    end repeat

    return (fileArray's |count|()) as integer
AS
}

function report () {
    /usr/bin/osascript <<AS
    use scripting additions

    display dialog "Folder:  ${1}" & return & return & ¬
    "Files:  ${2}" with title "File Count for Folder Hierarchy"
    return
AS
}

filecnt=$(hierarchyFileCount ${STARTDIR})
report $(print -Dl ${STARTDIR}) ${filecnt}
exit 0




Dec 12, 2022 9:24 AM in response to macsuperuser

The following will recursively count only the non-dot files in a selected Folder. It is a variation on the linked script above.


Code:


#!/bin/zsh

: <<"COMMENT"
Right-click on a folder in the Finder and then from the Finder's contextual menu,
select Quick Actions > Recursive Folder File Count.

Displays a dialog with the folder name and its contained file count.
COMMENT

typeset -a filecnt=()

function folder_count () {
    osascript <<AS
    display dialog "Folder:  " & "${1}" & return & "File count:  " & "${2}" ¬
    with title "Total Recursive File count for Folder"
AS
}

FOLDER="${1:a:s/\~\//}"

setopt nocaseglob
# recursively find all regular non-dot files in folder hierarchy
filecnt=( ${FOLDER}/**/*(.N) )
# pass folder name and array count of files in folder showing tilde path to folder
folder_count "$(print -Dl "${FOLDER:a}")" ${#filecnt[@]}
unset filecnt
exit 0



As an Automator Quick Action saved with name "Recursive Folder File Count":





Dec 18, 2022 2:32 PM in response to VikingOSX

And by the way, I just added some minimal code that if it encounters a package folder, add it to the file count without diving down into that package folder. Code works in the AppleScript editor, but identical code does not work in a Run AppleScript action because clicking the hammer icon (compile) of the AppleScript there forces some of the camelcase method name to lower case and the code fails when run for that reason.


This works in the Script Editor:


	repeat with afileRef in dirEnumerator's allObjects()
		set {result, isFile} to (afileRef's getResourceValue:(reference) forKey:NSURLIsRegularFileKey |error|:0)
		if (isFile's boolValue()) = true then
			(fileArray's addObject:(afileRef's valueForKey:"path"))
		else if (nsws's isFilePackageAtPath:(afileRef's valueForKey:"path")) = true then
			(fileArray's addObject:(afileRef's valueForKey:"path"))
		end if
	end repeat


and produces this result for one regular file and two package folder items at depth:



and the Automator Run AppleScript action does this to it:


	repeat with afileRef in dirEnumerator's allObjects()
		set {result, isFile} to (afileRef's getResourceValue:(reference) forKey:NSURLIsRegularFileKey |error|:0)
		if (isFile's boolValue()) = true then
			(fileArray's addObject:(afileRef's valueForKey:"path"))
		else if (nsws's isFilepackageAtPath:(afileRef's valueForKey:"path")) = true then
			(fileArray's addObject:(afileRef's valueForKey:"path"))
		end if
	end repeat


where the required uppercase 'P' in isFilePackageAtPath is changed to a lower case 'p' and the workflow fails because the method name is now wrong. I will be filing a bug report with Apple.

Dec 13, 2022 1:58 PM in response to VikingOSX

First I was very happy to see this post with a simple solution for a problem in my workspace.

On two different Macs I had a music-folder with more than 5000 songs in lots of subfolders.

Your quick-action is able to count the correct amount of mp3 and m4a files.


BUT: it seems to work ONLY with this folder. A folder with 10 empty subfolders was calculated by the action to have 728 files inside (!?!)


At least - at the moment not even ONE solution can bring correct results in every situation - that's really bad :-(

And apple itself cannot or don't want to give us a reliable App/Script/QuickAction or something else....


bye, peter

Dec 14, 2022 1:51 AM in response to macsuperuser

Scripts provided here are from fellow users contributing their time and code in an attempt to address a user-stated problem. Apple won't do this for obvious reasons, and the operating system has sufficient tools to build a solution without Apple's intervention.


If your deep folder hierarchy contained an application or other Apple package folder, then the script would have treated it like another directory and counted its individual file contents. Otherwise, if the folder hierarchy is completely devoid of files the count proves to be zero. I can add an additional test in the script to skip package folders in the folder hierarchy.

Dec 14, 2022 7:53 AM in response to VikingOSX

Thanks


I need this script for only ONE specific action - to count the sound-files in the music folder.

And for that reason your script works fantastic.

But I think it's on apple to build this feature into MacOS - Windows can do it since Win95 I think.

Apple offers me to count the Megabytes - I do really not need this information.


By the way.... the folder with 10 empty subfolders contained an installation file for macos ventura. That's why it counts 728 files in it :-) sorry about the confusion...

Dec 18, 2022 1:08 PM in response to VikingOSX

Thanks for all Your work, VikingOSX - it helps me a lot


Your first script was the better one, sorry :-) It shows the more correct results in my environment (Ventura 13.1).

The second one takes a lot more time to calculate, and shows incorrect results.

One folder with 12 empty subfolders. one contains a file "Install MacOS Ventura" which is a container.

Your first script comes back with a result of 721 files, possibly all the contents of the container.

The second script says "0", it does not recognize the container as a file.

I would expect a correct result of "1".


Thanks again, greetings from switzerland

Peter


Dec 18, 2022 1:41 PM in response to macsuperuser

The second script purposely avoids deep dives into special package folders that in layman's terms appear as files, but are technically folders with a bit set to make the Finder present them as though they were files. The script purposely excludes diving into these package folders as it would give you a misrepresentation of total files counted. Otherwise, if it encountered a monster package folder such as Xcode 14.2 ,it would return an additional 550+ K files to the count.


I tested this on Ventura 13.1 and in my ten folder deep test folder, I placed an Automator application at level 3 and it rightly came back with the 47 PNG images that were scattered at all levels, but excluded that application.

Dec 20, 2022 10:00 AM in response to VikingOSX

Your last script seems to be the best for now, but it takes a bit more time to count.

For this reason I call it now "Better FileCount" :-)


Strange behaviour....

I found some folders with an invisible File called "Info?" in it. These files correctly were not be counted by your last script. The first one counts them, but is completely disturbed bei these files - with an impossible result.


I think I will use only Better FileCount from now on.


Thanks a lot

Automator Quickaction "File Count" in folders and subfolders

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.