Want Folder name—only! Not path

Hi again all,

Been a while since I’ve been here. But I’m revisiting an older script that I’ve been using for quite some time. It reports the average file size in a folder, that the user chooses. After running, it gives one the total files, total size and average size of the folder in question.

But I would now like to add one additional tidbit. I’d like to get the Name of the folder in the display dialog as well. And I’m having some issues. Because I had initially set this up as a droplet-to-be I have run handlers inside it. Otherwise I know that get a folder name is pretty easy:

tell application "Finder"
	set FolderPath to (choose folder) -- sets file path to folder you select
	set Foldername to name of folder FolderPath -- sets the folder name as text
	display dialog "Folder: " & Foldername as text
end tell

But those pesky run handlers don’t like the above syntax and I can’t get it to run without reporting back the ENTIRE folder path. I just want the folder’s name. So my script, as is, looks like this:

on run
	choose folder with prompt "Calculate average file sizes in which folder?"
	open {result}
end run

on open user_Choice
	tell application "Finder" to set xx to every file in item 1 of user_Choice
	set tot_size to 0
	repeat with a_File in xx
		set tot_size to tot_size + ((info for (a_File as alias))'s size)
	end repeat
	display dialog ("Folder: " & user_Choice as text) & return & return & "Total files: " & (xx's length) & return & "Total size: " & ((round ((tot_size / 1.048576E+6) / 10)) / 100) & " GB" & return & "Average size: " & (((tot_size / 1.048576E+6) / (xx's length)) as integer) & " MB" buttons "OK" default button "OK"
end open

The ‘new addition’ as of now is this portion: "(“Folder: " & user_Choice as text) & return & return &” This script runs just fine. But the "Folder: " get populated with the entire path. If I try to combine the elements from my initial little snippet up top, into this one, then I end up with “can’t divide by zero” errors.

I know that I’m probably missing something rather small and simple. Something to do with run handlers, maybe? Anyway, any guidance is greatly appreciated. As always! Thanks.

Hi,

in the Finder tell block just get the name of the folder


tell application "Finder"
	set xx to every file in item 1 of user_Choice
	set folderName to name of item 1 of user_Choice
end tell

then display it instead of the path

display dialog ("Folder: " & folderName) & return & return ...

PS: The script will throw an error if the chosen folder doesn’t contain any files.

On my system the invisibles are always displayed so the script failed when it encountered a .DS_Store file.
Goog reason to drop the Fider whic I hate.

on run
	choose folder with prompt "Calculate average file sizes in which folder?"
	open {result}
end run

on open userChoice
	set theFolder to item 1 of userChoice
	tell application "System Events"
		set xx to every file in theFolder whose visible is true
		set folderName to name of theFolder
	end tell
	if (count xx) > 0 then
		set totalSize to 0
		repeat with aFile in xx
			set totalSize to totalSize + ((info for aFile)'s size)
		end repeat
		set totSize to its formatAsBytes:totalSize
		set averageSize to its formatAsBytes:(totalSize / (xx's length))
		display dialog "Folder: " & folderName & return & return & "Total files: " & (xx's length) & return & "Total size: " & ((round ((tot_size / 1.048576E+6) / 10)) / 100) & " GB" & return & "Average size: " & (((tot_size / 1.048576E+6) / (xx's length)) as integer) & " MB" buttons "OK" default button "OK"
	else
		display dialog ("Folder: " & folderName) & return & return & "contains no file."
	end if
end open

It works but on my test folder the sizes were reported as 0.0 which is not satisfying.

I decided to put ASObjC at work to get rid of that.

use AppleScript version "2.3.1"
use scripting additions
use framework "Foundation"

on run
	choose folder with prompt "Calculate average file sizes in which folder?"
	open {result}
end run

on open userChoice
	set theFolder to item 1 of userChoice
	tell application "System Events"
		set xx to every file in theFolder whose visible is true
		set folderName to name of theFolder
	end tell
	if (count xx) > 0 then
		set totalSize to 0
		repeat with aFile in xx
			set totalSize to totalSize + ((info for aFile)'s size)
		end repeat
		set totSize to its formatAsBytes:totalSize
		set averageSize to its formatAsBytes:(totalSize / (xx's length))
		display dialog ("Folder: " & folderName) & return & return & "Total files: " & (xx's length) & return & "Total size: " & (totSize & return & "Average size: " & averageSize) buttons "OK" default button "OK"
	else
		display dialog ("Folder: " & folderName) & return & return & "contains no file."
	end if
end open

on formatAsBytes:theValue
	set theNSByteCountFormatter to current application's NSByteCountFormatter's alloc()'s init()
	theNSByteCountFormatter's setIncludesActualByteCount:false
	return (theNSByteCountFormatter's stringFromByteCount:theValue) as text
end formatAsBytes:

Now the result is satisfying.
[format]tell application “Script Editor”
display dialog "Folder: tester

Total files: 4
Total size: 410 Ko
Average size: 103 Ko" buttons “OK” default button “OK”
end tell[/format]

On a larger folder it returned :
[format]tell application “Script Editor”
display dialog "Folder: tempo

Total files: 300
Total size: 2,23 Go
Average size: 7,4 Mo" buttons “OK” default button “OK”
end tell[/format]

Of course it would be interesting to use ASObjC to list the folder’s content and the total and average sizes but it’s an other story.

Yvan KOENIG running El Capitan 10.11.5 in French (VALLAURIS, France) samedi 11 juin 2016 12:14:26

It’s also reasonably complex because you need to fully enumerate any packages, while ignoring folders. There are also different measurements of size, depending on whether you include metadata. But this should match what’s been posted in functionality. It should also be quicker.

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

set thePath to POSIX path of (choose folder)
set {theName, theCount, theTotal} to my totalSizeIn:thePath
if theCount > 0 then
	set totSize to my formatAsBytes:theTotal
	set averageSize to my formatAsBytes:(theTotal / theCount)
	display dialog ("Folder: " & theName & return & return & "Total files: " & theCount & return & "Total size: " & totSize & return & "Average size: " & averageSize) buttons "OK" default button "OK"
else
	display dialog ("Folder: " & theName & return & return & "contains no file.") buttons "OK" default button "OK"
end if

on totalSizeIn:folderPosixPath
	set theNSURL to current application's class "NSURL"'s fileURLWithPath:folderPosixPath
	set theName to theNSURL's lastPathComponent() as text
	set theNSFileManager to current application's NSFileManager's defaultManager()
	set sizeKey to current application's NSURLTotalFileSizeKey
	set theURLs to theNSFileManager's contentsOfDirectoryAtURL:theNSURL includingPropertiesForKeys:{current application's NSURLIsDirectoryKey, current application's NSURLIsPackageKey, current application's NSURLTotalFileSizeKey} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value) -- skip hidden
	set theTotal to 0
	set theCount to 0
	repeat with anNSURL in theURLs
		set {theResult, isDirectory} to (anNSURL's getResourceValue:(reference) forKey:(current application's NSURLIsDirectoryKey) |error|:(missing value))
		if isDirectory as boolean then
			set {theResult, isPackage} to (anNSURL's getResourceValue:(reference) forKey:(current application's NSURLIsPackageKey) |error|:(missing value))
			if isPackage as boolean then
				-- it's a package
				set theCount to theCount + 1
				set theTotal to theTotal + (my sizeOfDirectoryAt:anNSURL)
			else
				-- It's a folder; ignore
			end if
		else
			-- it's a file
			set theCount to theCount + 1
			set {theResult, theSize} to (anNSURL's getResourceValue:(reference) forKey:sizeKey |error|:(missing value))
			if theSize is not missing value then set theTotal to theTotal + (theSize as real)
		end if
	end repeat
	return {theName, theCount, theTotal}
end totalSizeIn:

on sizeOfDirectoryAt:dirURL -- used for packages
	set theNSFileManager to current application's NSFileManager's defaultManager()
	set theEnumerator to theNSFileManager's enumeratorAtURL:dirURL includingPropertiesForKeys:{current application's NSURLIsDirectoryKey, current application's NSURLTotalFileSizeKey} options:0 errorHandler:(missing value) -- don't skip any
	set subURLs to theEnumerator's allObjects()
	set theTotal to 0
	repeat with anNSURL in subURLs
		set {theResult, isDir} to (anNSURL's getResourceValue:(reference) forKey:(current application's NSURLIsDirectoryKey) |error|:(missing value))
		if not (isDir as boolean) then
			set {theResult, theSize} to (anNSURL's getResourceValue:(reference) forKey:(current application's NSURLTotalFileSizeKey) |error|:(missing value))
			if theSize is not missing value then set theTotal to theTotal + (theSize as real)
		end if
	end repeat
	return theTotal
end sizeOfDirectoryAt:

on formatAsBytes:theValue
	return (current application's NSByteCountFormatter's stringFromByteCount:theValue countStyle:(current application's NSByteCountFormatterCountStyleDecimal)) as text
end formatAsBytes:

Edited to allow for empty folder

Hello Shane

While you posted I was coding an alternate scheme.
Here it is.

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

on getSomeStats:folderPath
	# Use a script object in case of large number of files
	script o
		property theFiles : {}
		property theSizes : {}
	end script
	set theURL to current application's class "NSURL"'s fileURLWithPath:folderPath
	set fileManager to current application's NSFileManager's defaultManager()
	set theOptions to current application's NSDirectoryEnumerationSkipsHiddenFiles as integer
	set o's theFiles to fileManager's contentsOfDirectoryAtURL:theURL includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles as integer) |error|:(missing value)
	repeat with aURL in o's theFiles
		set {theSize, theError} to (aURL's resourceValuesForKeys:{current application's NSURLFileSizeKey} |error|:(reference))
		set theSize to theSize as record
		if theSize is not {} then # skip packages and folders
			set end of o's theSizes to NSURLFileSizeKey of theSize
		end if
	end repeat
	set nbFiles to count o's theSizes
	if nbFiles > 0 then
		set o's theSizes to current application's NSArray's arrayWithArray:(o's theSizes)
		set theSum to its formatAsBytes:(((o's theSizes)'s valueForKeyPath:"@sum.self") as real)
		set theAvg to its formatAsBytes:(((o's theSizes)'s valueForKeyPath:"@avg.self") as real)
		return {nbFiles, theSum, theAvg}
	else
		return {0, 0, 0}
	end if
end getSomeStats:

on formatAsBytes:theValue
	set theNSByteCountFormatter to current application's NSByteCountFormatter's alloc()'s init()
	theNSByteCountFormatter's setIncludesActualByteCount:false
	return (theNSByteCountFormatter's stringFromByteCount:theValue) as text
end formatAsBytes:

set theFolder to POSIX path of (choose folder)
tell application "System Events"
	set foldername to name of folder theFolder
end tell
set {nbFiles, theSum, theAvg} to its getSomeStats:theFolder
if {nbFiles, theSum, theAvg} is not {0, 0, 0} then
	display dialog ("Folder: " & foldername & return & return & "Total files: " & nbFiles & return & "Total size: " & theSum & return & "Average size: " & theAvg) buttons "OK" default button "OK"
else
	display dialog ("Folder: " & foldername) & return & return & "contains no file."
end if

Yvan KOENIG running El Capitan 10.11.5 in French (VALLAURIS, France) samedi 11 juin 2016 15:41:12

Yvan pointed out that my script would fail if there are no files; I’ve made his suggested change above.

Wow, it’s crazy to watch where things end up. But so far, this version is working perfectly for my needs! Thanks for the guidance.

…and the additional iterations are always appreciated too. :slight_smile: