-- saves names of folders as blue, names of files - as green
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
use framework "AppKit"
property |NSURL| : a reference to current application's |NSURL|
property NSFileManager : a reference to current application's NSFileManager
property NSFont : a reference to current application's NSFont
property NSAttributedString : a reference to current application's NSAttributedString
property NSMutableAttributedString : a reference to current application's NSMutableAttributedString
property NSColor : a reference to current application's NSColor
property NSDictionary : a reference to current application's NSDictionary
property NSString : a reference to current application's NSString
-- user settings
set rootFolderPath to POSIX path of (choose folder with prompt "Choose the root folder")
set LF to (NSString's stringWithString:linefeed)
set theFont to NSFont's fontWithName:"Geneva" |size|:14.0
set blue to NSColor's colorWithCalibratedRed:0.0 green:0.0 blue:0.6 alpha:1.0
set blueText to NSDictionary's dictionaryWithObject:blue forKey:"NSColor"
set green to NSColor's colorWithCalibratedRed:0.0 green:0.4 blue:0.0 alpha:1.0
set greenText to NSDictionary's dictionaryWithObject:green forKey:"NSColor"
set rootAndContainerRegex to "^" & rootFolderPath & "|[^/]++/"
set theFileManager to NSFileManager's defaultManager()
-- get entire contents of root folder
set rootURL to |NSURL|'s fileURLWithPath:rootFolderPath
set logFilePath to POSIX path of ((path to desktop as text) & "Folder Hierarchy.rtf")
set logFileURL to |NSURL|'s fileURLWithPath:logFilePath
set theEnumerator to theFileManager's enumeratorAtURL:rootURL ¬
includingPropertiesForKeys:{"NSURLIsDirectoryKey", "NSURLIsPackageKey"} ¬
options:6 errorHandler:(missing value)
set entireContents to theEnumerator's allObjects()
-- Initialise an NSMutableAttributedString with the title line and two linefeeds.
set styledText to NSMutableAttributedString's alloc()'s ¬
initWithString:("Start " & (current date) & linefeed & linefeed)
-- Start a "run" of folder names with the name of the root folder.
set currentRun to rootURL's lastPathComponent()'s mutableCopy()
set isFileRun to false
repeat with thisItem in entireContents
set thisPath to thisItem's |path|()
-- Replace the root path and any other container components in this path with spaces, leaving just an indented name.
set indentedName to (thisPath's stringByReplacingOccurrencesOfString:rootAndContainerRegex withString:(" ") options:1024 range:({location:0, |length|:thisPath's |length|()}))
-- Append to a linefeed, ready for appending to the preceding text.
set indentedNameLine to (LF's stringByAppendingString:indentedName)
-- Get this item's directory and package flags. If they're equal, the item's either a file or a package. Otherwise it's a folder.
set dpDictionary to (thisItem's resourceValuesForKeys:{"NSURLIsDirectoryKey", "NSURLIsPackageKey"} |error|:(missing value))
set treatingAsFile to ((dpDictionary's objectForKey:"NSURLIsDirectoryKey")'s isEqual:(dpDictionary's objectForKey:"NSURLIsPackageKey")) as boolean
-- Is the item of the same type as for the current run of names?
if treatingAsFile = isFileRun then
-- If so, simply append its indented name to the run text.
tell currentRun to appendString:indentedNameLine
else
-- Otherwise, make an NSAttributedString with the current run text, coloured or not as appropriate.
if isFileRun then
set thisColourBlock to (NSAttributedString's alloc()'s initWithString:currentRun attributes:greenText)
else
set thisColourBlock to (NSAttributedString's alloc()'s initWithString:currentRun attributes:blueText)
end if
-- Append this to the main styled text.
tell styledText to appendAttributedString:thisColourBlock
-- Start a new run text with the current name line and set the run-type flag accordingly.
set currentRun to indentedNameLine's mutableCopy()
set isFileRun to treatingAsFile
end if
end repeat
-- Append the final run to the styled text at the end.
if (isFileRun) then
set thisColourBlock to (NSAttributedString's alloc()'s initWithString:currentRun attributes:greenText)
else
set thisColourBlock to (NSAttributedString's alloc()'s initWithString:currentRun attributes:blueText)
end if
tell styledText to appendAttributedString:thisColourBlock
tell styledText to addAttribute:"NSFont" value:theFont range:{location:0, |length|:its |length|()}
-- Extract RTF data from the styled text and save using a URL derived from the given log file path.
set theRTFData to styledText's RTFFromRange:{location:0, |length|:styledText's |length|()} documentAttributes:(missing value)
tell theRTFData to writeToURL:logFileURL atomically:true
display notification "Folder hierarchy RTF" & linefeed & "created on the desktop." with title "Folder hierarchy.script"