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.
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:
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