Mac OS X Finder

The following snippets contain some duplicate code and patterns, but in most cases that is just wrapper code to facilitate the real function.

Combo droplet/app for processing any number of files

This is a framework for an Applescript app that can be used as both a droplet and an app. This framework allows processing of any combination of files and folders dropped on it. Allowing a script to be used as both a droplet or an app allows for the greatest ease of use for non-scripters who may be unfamiliar with using a script from Script Editor.
There are two points of customization:

  • createFileList to collect and process only targeted files (i.e., art files of specific types, Word documents).
  • ProcessFile where a file path is given and is made available to process after all target files have been collected.
property kSourceFolder : ""
property kDestinationFolder : ""

property pErrorLog : {}
property pFileList : {}

on run {}
	-- Executed when the script is opened by clicking

	set kSourceFolder to choose folder with prompt "Please select a folder that contains files."
	set kDestinationFolder to choose folder with prompt "Please select a DIFFERENT folder to save the updated files."
	my createFileList(kSourceFolder)
	my ProcessFiles(pFileList)
	my OutputErrorLog(pErrorLog)

end run

on open of theFiles
	--	Executed when files are dropped on the script

	set lastFile to count theFiles
	repeat with thisFile from 1 to lastFile
		set theFile to item thisFile of theFiles
		my createFileList(theFile)
	end repeat

	my ProcessFiles(pEpsFiles)
	my OutputErrorLog(pErrorLog)

end open

on ProcessFiles(FileList) -- (list of file paths) as void

	set lastFile to count FileList
	repeat with thisFile from 1 to lastFile
		set theFile to item thisFile of FileList
		my ProcessFile(theFile)
	end repeat

end ProcessFiles

on ProcessFile(FilePath) -- (file path) as void

	set pathComponents to GetPathComponentsFromAlias(FilePath) of me

	(* processing code starts here *)

end ProcessFile

on LogError(ErrorText)
	set theDate to (current date)
	set loggedError to theDate & " | " & ErrorText
	set end of pErrorLog to loggedError
end LogError

on OutputErrorLog(ErrorLog) -- (list of strings) as void
	set lastLogItem to count ErrorLog
	repeat with thisLogItem from 1 to lastLogItem
		set theLogItem to item thisLogItem of ErrorLog
		my WriteLog(theLogItem)
	end repeat
end OutputErrorLog

on ResetGlobalVariables()

	set kSourceFolder to ""
	set kDestinationFolder to ""

	set pErrorLog to {}
	set pFileList to {}

end ResetGlobalVariables

on createFileList(source_item) -- (path || alias) as void

	set file_info to ""

	tell application "System Events"
		set file_info to get info for source_item
	end tell

	if visible of file_info is false then
		return
	end if

	if folder of file_info is true then

		set item_list to ""

		tell application "System Events"
			set item_list to get the name of every disk item of (source_item as alias)
		end tell

		set item_count to (get count of items in item_list)

		repeat with this_item from 1 to item_count

			set the_properties to ""

			set the_item to item this_item of the item_list
			set the_item to1 as string
	set posixPath to trim_line(posixPath, "/", 1) of me
	set posixPath to EscapeSpacesInPath(posixPath) of me
	return (posixPath & ".zip") as string
end MakeZipPath

on DeleteFolder(folderPath) -- (string) as void
	tell application "Finder"
		set folderMoved to move folderPath to trash
	end tell
end DeleteFolder

on createList(mSource_folder) -- (string) as void
	set item_list to ""

	tell application "System Events"
		set item_list to get the name of every disk item of (mSource_folder as alias)
	end tell

	set item_count to (get count of items in item_list)

	repeat with i from 1 to item_count
		set the_properties to ""

		set the_item to item i of the item_list
		if character 1 of the_item is not "." then
			set the_item to ((mSource_folder & the_item) as string) as alias

			tell application "System Events"
				set file_info to get info for the_item
			end tell

			if visible of file_info is true then
				set file_name to displayed name of file_info
				if folder of file_info is true then
					if file_name contains "Fonts" or file_name contains "fonts" or file_name contains "FONTS" then
						set end of pFileList to the_item
					end if
					my createList(the_item)
				end if
			end if
		end if
	end repeat
end createList

on trim_line(this_text, trim_chars, trim_indicator)
	-- 0 = beginning, 1 = end, 2 = both
	set x to the length of the trim_chars
	-- TRIM BEGINNING
	if the trim_indicator is in {0, 2} then
		repeat while this_text begins with the trim_chars
			try
				set this_text to characters (x + 1) thru -1 of this_text as string
			on error
				-- the text contains nothing but the trim characters
				return ""
			end try
		end repeat
	end if
	-- TRIM ENDING
	if the trim_indicator is in {1, 2} then
		repeat while this_text ends with the trim_chars
			try
				set this_text to characters 1 thru -(x + 1) of this_text as string
			on error
				-- the text contains nothing but the trim characters
				return ""
			end try
		end repeat
	end if
	return this_text
end trim_line

on replace_chars(this_text, search_string, replacement_string)
	set AppleScript's text item delimiters to the search_string
	set the item_list to every text item of this_text
	set AppleScript's text item delimiters to the replacement_string
	set this_text to the item_list as string
	set AppleScript's text item delimiters to ""
	return this_text
end replace_chars

Compress every item in a Folder

This is very similar to the above script, except for these important differences:

  • The target file is deleted when it has been compressed.
  • It is written to be used in the Applescript menu in the Finder’s menubar.
  • It is non-recursive (though it would be a snap to make it so, but then it wouldn’t be able to handle folders like this one can).
property CompressCommand : "zip "
property CompressedFileExtension : ".zip"
property QuoteMark : "'"

on run {}
	set OriginalFolder to ""
	try
		tell application "Finder" to set the OriginalFolder to (folder of the front window) as alias
	on error -- no open folder windows
		set OriginalFolder to (choose folder) as alias
	end try

	set item_list to CreateList(OriginalFolder)

	set item_count to (get count of items in item_list)

	repeat with i from 1 to item_count
		set theItem to item i of item_list
		set theItemPath to (OriginalFolder & theItem) as string
		my CompressItem(theItemPath)
	end repeat

	beep

end run

on CreateList(SourceFolder)
	set item_list to {}

	tell application "System Events"
		set item_list to get the name of every disk item of (SourceFolder as alias)
	end tell

	return item_list
end CreateList

on CompressItem(theItem)

	set ParentFolder to ""
	set FileName to ""

	tell application "Finder"
		set ParentFolder to container of (theItem as alias) as alias
		set FileName to name of (theItem as alias)
	end tell

	set PathToInput to (quoted form of POSIX path of theItem)
	set PathToOutPut to (QuoteMark & POSIX path of ParentFolder & FileName & CompressedFileExtension & QuoteMark)

	do shell script "ditto -ck " & PathToInput & " " & PathToOutPut

	tell application "Finder"
		set theResult to delete theItem
	end tell
end CompressItem

Create Timestamp to Format

A low-level helper script to create time stamps for a variety of needs and drops them in the clipboard for quick use. Fast, cheap, and easy to update as well. This could stand a few improvements, tweaks mostly, but I think this offers a good example of several different ways text can be manipulated in Applescript using the subroutines found here and elsewhere.

on run {}

	-- set the choices
	set kDateFormat to "YY/MM/DD"
	set kTimeFormat to "hh:mm:ss"
	set kDateTimeFormat to "YY/MM/DD hh:mm:ss"
	set kBugStamp to "YYMMDDhhmmss"

	-- display the choices
	set choices to {kDateFormat, kTimeFormat, kDateTimeFormat, kBugStamp}
	set theChoice to (choose from list choices with prompt "Stamp format" without multiple selections allowed) as text

	-- handle the choice accordingly
	if theChoice is not "False" then

		-- move forward with making the stamp

		-- set the globals
		set finalFormat to ""
		set now to getFinderTimeStamp()

		if theChoice is kDateFormat then
			set finalFormat to dateStamp(now) of me
		end if

		if theChoice is kTimeFormat then
			set finalFormat to timeStamp(now) of me
		end if

		if theChoice is kDateTimeFormat then
			set finalFormat to dateTimeStamp(now) of me
		end if

		if theChoice is kBugStamp then
			set finalFormat to bugStamp(now) of me
		end if

		-- push to the clipboard
		tell application "Finder"
			set the clipboard to finalFormat as text
			beep
		end tell

	else
		-- cancelled; do nothing
	end if

end run

-- make the various stamps

on dateStamp(now)
	return JoinList({item 1 of now, item 2 of now, item 3 of now}, "/")
end dateStamp

on timeStamp(now)
	return JoinList({item 4 of now, item 5 of now, item 6 of now}, ":")
end timeStamp

on dateTimeStamp(now)
	return JoinList({my dateStamp(now), my timeStamp(now)}, " ")
end dateTimeStamp

on bugStamp(now)
	return JoinList(now, "")
end bugStamp

-- get and prep the chronological data

on getFinderTimeStamp()
	tell application "Finder"
		set theDate to (current date)
		set theDay to day of theDate as text
		set theMonth to (month of theDate as integer) as string
		set theYear to year of theDate as text
		set theYear to _getTimeStamp_RemoveCenturyFromYear(theYear) of me
		set theTime to time string of theDate
		set theTime to _getTimeStamp_GetTimeComponents(theTime) of me
		return {theYear, theMonth, theDay, item 1 of theTime, item 2 of theTime, item 3 of theTime}
	end tell
end getFinderTimeStamp

on _getTimeStamp_RemoveCenturyFromYear(theYear) -- (integer) as string
	return characters 3 thru 4 of theYear as text
end _getTimeStamp_RemoveCenturyFromYear

on _getTimeStamp_GetTimeComponents(theTimeString) -- (string) as list of strings
	-- "hh:mm:ss AM"
	set theMainComponents to SplitString(theTimeString, " ") of me
	--{"hh:mm:ss", "AM"}
	return SplitString(item 1 of theMainComponents, ":") of me
	--{"hh", "mm", "ss"}
end _getTimeStamp_GetTimeComponents

-- helper subroutines

on replace_chars(this_text, search_string, replacement_string)
	set AppleScript's text item delimiters to the search_string
	set the item_list to every text item of this_text
	set AppleScript's text item delimiters to the replacement_string
	set this_text to the item_list as string
	set AppleScript's text item delimiters to ""
	return this_text
end replace_chars

on JoinList(theList, TheDelimiter)
	set AppleScript's text item delimiters to {TheDelimiter}
	set TheListAsText to theList as text
	set AppleScript's text item delimiters to ""
	return TheListAsText
end JoinList

on SplitString(theString, TheDelimiter) -- (string, string) as list
	set AppleScript's text item delimiters to {TheDelimiter}
	set theStringList to (every text item in theString) as list
	set AppleScript's text item delimiters to ""
	return theStringList
end SplitString

  1. source_item & the_item) as string) as alias tell application "System Events" set file_info to get info for the_item end tell if visible of file_info is true then if folder of file_info is true then my createFileList(the_item) else my processFileForList(the_item) end if -- folder end if -- visible end repeat -- items in source_item else my processFileForList(source_item) end if -- folder end createFileList on processFileForList(FilePath) -- (path || alias) as void set pathComponents to GetPathComponentsFromAlias(FilePath) of me if fileExtension of pathComponents contains "eps" then set end of pEpsFiles to FilePath end if end processFileForList on GetPathComponentsFromAlias(FilePath) -- (alias) as string set theFilePath to FilePath as string set AppleScript's text item delimiters to {":"} set thePathComponents to (get every text item in theFilePath) as list set AppleScript's text item delimiters to "" set theFullFileName to (get item (count thePathComponents) of thePathComponents) set AppleScript's text item delimiters to {"."} set theFileNameComponents to (get every text item in theFullFileName) as list set AppleScript's text item delimiters to "" set theFilename to theFullFileName set theFileExtension to "" if (count theFileNameComponents) > 1 then set theFilename to item 1 of theFileNameComponents set theFileExtension to item 2 of theFileNameComponents end if return {fullFileName:theFullFileName, fileName:theFilename, fileExtension:theFileExtension, sourceFilePath:theFilePath} end GetPathComponentsFromAlias on WriteLog(the_text) set this_story to the_text set this_file to (((path to desktop folder) as text) & "FlaggedFileLog.txt") my write_to_file(this_story, this_file, true) end WriteLog on write_to_file(this_data, target_file, append_data) try set the target_file to the target_file as text set the open_target_file to ¬ open for access file target_file with write permission if append_data is false then ¬ set eof of the open_target_file to 0 write this_data to the open_target_file starting at eof close access the open_target_file return true on error try close access file target_file end try return false end try end write_to_file

    Check if a file exists with System Events

    This is a better way to see if a file exists than using set theFile to theFile as alias. If anything, using file exists won’t throw an exception if the file doesn’t exist.

    on FileExists(theFile) -- (String) as Boolean
    	tell application "System Events"
    		if exists file theFile then
    			return true
    		else
    			return false
    		end if
    	end tell
    end FileExists

    Volumes

    This bit of code shows how to mount a volume requiring a login, and then open a file on that volume. It returns a disk object for easy unmounting later. To get to a specific location or file on the server, it would probably be best to use the POSIX path to generate the alias.

    tell application "Finder"
    	try
    		set TheServer to mount volume "smb://bullet.jbpub.com/FTP/" as user name “” with password “” -- unless you have some clever way to obfuscate this, this is how it is hard-coded.
    	on error --number -55
    		set VolumeCount to (get count of disks)
    		repeat with x from 1 to VolumeCount
    			set thisVolume to disk x
    			if name of thisVolume is "FTP" then
    				set TheServer to thisVolume
    				exit repeat
    			end if
    		end repeat
    	end try
    	set TheServerPath to TheServer as string
    	set theFile to TheServerPath & "PhilipR:Untitled.scpt"
    	set theFile to theFile as alias
    	open theFile
    end tell

    Get Path To Me

    This chunk of code was written as an ease-of-use function for non-technical AS users. It is used to get the exact location of the script and is used to get files that are always in the same location in relation to the script application. So, a user can just double-click start or file drop start on the app, and the app can figure out where it is and where it needs to go.

    on GetPathToMe()
    	set pathToMe to (get path to me) as string
    	set AppleScript's text item delimiters to ":"
    	set pathArray to (every text item in pathToMe) as list
    	set AppleScript's text item delimiters to ""
    	set creationFolderPath to ""
    	--the "- 2" in the iteration statement is how far up the path to go to get to the needed files sitting near the app.
    	repeat with x from 1 to ((get count of items in pathArray) - 2)
    		set thisDirectory to item x of pathArray
    		set creationFolderPath to creationFolderPath & thisDirectory & ":"
    	end repeat
    	return creationFolderPath
    end GetPathToMe

    Get Path Components From Alias

    In a lot of my larger scripts, or at least ones where I do a lot of image processing in nested folders, I typically start with a file path culled from “List Files” and from there I grab the bits of the path and file name I need. Before I was doing this as simple operations from within the code, but creating a subroutine and returning a record makes this much more handy because now I can have all the components calculatedonce and use that instead of just plain file paths. I’ve also considered having it record the parent folder of a file so that I don’t have to make a call to System Events each time I need that. String operations, I think, are faster and simpler to manage with this already in place.

    on GetPathComponentsFromAlias(FilePath) -- (alias) as string
    	set theFilePath to FilePath as string
    
    	set AppleScript's text item delimiters to {":"}
    	set thePathComponents to (get every text item in theFilePath) as list
    	set AppleScript's text item delimiters to ""
    
    	set theFullFileName to (get item (count thePathComponents) of thePathComponents)
    
    	set AppleScript's text item delimiters to {"."}
    	set theFileNameComponents to (get every text item in theFullFileName) as list
    	set AppleScript's text item delimiters to ""
    
    	set theFileName to theFullFileName
    	set theFileExtension to ""
    
    	if (count theFileNameComponents) > 1 then
    		set theFileName to item 1 of theFileNameComponents
    		set theFileExtension to item 2 of theFileNameComponents
    	end if
    
    	return {fullFileName:theFullFileName, fileName:theFileName, fileExtension:theFileExtension, sourceFilePath:theFilePath}
    end GetPathComponentsFromAlias

    Image Events

    I always forget how cool this is until someone asks about it.

    Get Image Dimensions with Image Events

    Image Events has many uses, but here it offers an easy way to get basic image information without the need for Photoshop. It is likely that the Finder application uses this library or it calls to the same library that Image Events calls to.

    on GetImageDimensions(theFile)
    	tell application "Image Events"
    		launch --we have to launch Image Events before we can use it
    		set theImage to open theFile
    		set theImageDimensions to dimensions of theImage
    		set theImageWidth to item 1 of theImageDimensions
    		set theImageHeight to item 2 of theImageDimensions
    		return {theImageWidth, theImageHeight}
    	end tell
    end GetImageDimensions

    Whole Script: Convert Image Files

    property kFileList : {}
    
    tell application "Finder"
    	set theSourceFolder to choose folder
    	set theDestinationFolder to choose folder
    
    	my createList(theSourceFolder)
    
    	set lastItem to (count kFileList)
    	repeat with thisItem from 1 to lastItem
    		set theFile to (theSourceFolder & item thisItem of kFileList) as string
    
    		tell application "Image Events"
    			set theImage to open theFile
    			save theImage as JPEG2 in ((theDestinationFolder & item thisItem of kFileList & ".jpg") as string) with compression level high
    		end tell
    	end repeat
    end tell
    
    on createList(mSource_folder)
    	set item_list to ""
    
    	tell application "System Events"
    		set item_list to get the name of every disk item of mSource_folder
    	end tell
    
    	set item_count to (get count of items in item_list)
    
    	repeat with i from 1 to item_count
    		set the_properties to ""
    
    		set the_item to item i of the item_list
    		set the_item to ((mSource_folder & the_item) as string) as alias
    
    		tell application "System Events"
    			set file_info to get info for the_item
    		end tell
    
    		if visible of file_info is true then
    			set file_name to displayed name of file_info
    			set end of kFileList to file_name
    			if folder of file_info is true then
    				my createList(the_item)
    			end if
    		end if
    
    	end repeat
    end createList

    Work with specific file types from what was dropped on the application

    property kTargetFileExtensions : {"txt", "rtf", "pdf"}
    property pValidFileList : {}
    
    on open of theFiles -- Executed when files or folders are dropped on the script
    
    	set fileCount to (get count of items in theFiles)
    
    	repeat with thisFile from 1 to fileCount
    		set theFile to item thisFile of theFiles
    
    		my processInitialFile(theFile)
    
    	end repeat
    
    	my processValidFileList()
    
    end open
    
    on run {} -- Executed when the script is run from within the editor
    	set sourceFolder to (choose folder)
    
    	my processInitialFile(sourceFolder)
    
    	my processValidFileList()
    end run
    
    on processInitialFile(theFile)
    	tell application "System Events"
    		set file_info to get info for theFile
    	end tell
    
    	if visible of file_info is true then -- check for the file extension here as well
    		if folder of file_info is true then
    			my createList(theFile)
    		else
    			set targetFileFound to isTargetFile(fileName, kTargetFileExtensions) of me
    
    			if (targetFileFound) then
    				set end of pValidFileList to theFile
    			end if
    		end if
    	end if
    end processInitialFile
    
    on processValidFileList() -- (void) as void
    	set firstFile to 1
    	set lastFile to (count pValidFileList)
    	repeat with thisFile from firstFile to lastFile
    		set theFile to item thisFile of pValidFileList
    
    		log theFile
    
    		(* enter file processing code here. *)
    
    	end repeat
    
    end processValidFileList
    
    on createList(mSource_folder)
    	set item_list to ""
    
    	tell application "System Events"
    		set item_list to get the name of every disk item of (mSource_folder as alias)
    	end tell
    
    	set item_count to (get count of items in item_list)
    
    	repeat with i from 1 to item_count
    		set the_properties to ""
    
    		set the_item to item i of the item_list
    		set fileName to the_item
    		set the_item to ((mSource_folder & the_item) as string) as alias
    
    		tell application "System Events"
    			set file_info to get info for the_item
    		end tell
    
    		if visible of file_info is true then -- check for the file extension here as well
    			if folder of file_info is true then
    				my createList(the_item)
    			else
    				set targetFileFound to isTargetFile(fileName, kTargetFileExtensions) of me
    
    				if (targetFileFound) then
    					set end of pValidFileList to the_item
    				end if
    			end if
    		end if
    
    	end repeat
    end createList
    
    on isTargetFile(theFilename, theTargetExtensions) -- (string, array) as boolean
    	set AppleScript's text item delimiters to "."
    	set fileNameList to every text item of theFilename
    	set AppleScript's text item delimiters to ""
    
    	try
    		set theFileExtension to item 2 of fileNameList as string
    	on error
    		return false
    	end try
    
    	set firstTargetExtension to 1
    	set lastTargetExtension to (count theTargetExtensions)
    	repeat with thisTargetExtension from firstTargetExtension to lastTargetExtension
    		set targetExtension to item thisTargetExtension of theTargetExtensions
    		if theFileExtension is targetExtension then
    			return true
    		end if
    	end repeat
    
    	return false
    end isTargetFile

    List Files (Recursive Finder operation)

    property kFileList : {}
    
    tell application "Finder"
        set source_folder to choose folder with prompt "Please select directory."
        my createList(source_folder)
    end tell
    
    return kFileList
    
    on createList(mSource_folder)
        set item_list to ""
    
        tell application "System Events"
            set item_list to get the name of every disk item of (mSource_folder as alias)
        end tell
    
        set item_count to (get count of items in item_list)
    
        repeat with i from 1 to item_count
            set the_properties to ""
    
            set the_item to item i of the item_list
            set the_item to ((mSource_folder & the_item) as string) as alias
    
            tell application "System Events"
                set file_info to get info for the_item
            end tell
    
            if visible of file_info is true then
                set file_name to displayed name of file_info
                set end of kFileList to file_name
                if folder of file_info is true then
                    my createList(the_item)
                end if
            end if
    
        end repeat
    end createList

    Remove invisible svn hooks from project folder

    This was written to move a version-controlled project folder from one svn project to another. I use Versions to help me manage my version-controlled projects and they don’t have (at the time of this writing on 30 August 2010) a way to change the project URL. This simply removes all of the project folders to prepare if for migration. Not very useful in the late stages of a project, but good for one of those “Oops!” moments.

    property kSVNFolderName : "svn"
    property kFileList : {}
    
    tell application "Finder"
    	set source_folder to choose folder with prompt "Please select directory."
    	my createList(source_folder)
    
    	set folderCount to (get count of items in kFileList)
    
    	repeat with thisFolder from 1 to folderCount
    		set theFolder to item thisFolder of kFileList
    		set theFolderIsTrashed to move theFolder to trash
    	end repeat
    
    end tell
    
    on createList(mSource_folder)
    	set item_list to ""
    
    	tell application "System Events"
    		set item_list to get the name of every disk item of mSource_folder
    	end tell
    
    	set item_count to (get count of items in item_list)
    
    	repeat with i from 1 to item_count
    		set the_properties to ""
    
    		set the_item to item i of the item_list
    		set the_item to ((mSource_folder & the_item) as string) as alias
    
    		tell application "System Events"
    			set file_info to get info for the_item
    		end tell
    
    		set file_name to displayed name of file_info
    		if file_name ends with kSVNFolderName then
    			set end of kFileList to the_item
    		end if
    
    		if folder of file_info is true then
    			my createList(the_item)
    		end if
    
    	end repeat
    end createList

    Reprocess/Rename files made into iWeb gallery

    global gSourceFolder
    global gDestinationFolder
    
    set gSourceFolder to choose folder
    set gDestinationFolder to choose folder
    
    tell application "Finder"
    
    	set theTopFolderList to list folder gSourceFolder without invisibles
    	set lastFolder to get count of items in theTopFolderList
    	repeat with thisFolder from 1 to lastFolder
    		set theFolder to item thisFolder of theTopFolderList
    		set theMediaFolder to ((gSourceFolder & theFolder & ":Media:") as string) as alias
    
    		set theMediaFolderList to list folder theMediaFolder without invisibles
    		set lastImageFolder to get count of items in theMediaFolderList
    		repeat with thisImageFolder from 1 to lastImageFolder
    			set theImageFolder to item thisImageFolder of theMediaFolderList
    			set theImageFolderName to item thisImageFolder of theMediaFolderList
    			set theImageFolder to ((theMediaFolder & theImageFolder & ":") as string) as alias
    
    			set theImage to ((theImageFolder & "web.jpg") as string) as alias
    
    			set name of theImage to (theImageFolderName & ".jpg") as string
    			set fileMoved to move theImage to gDestinationFolder
    
    		end repeat -- image folder
    	end repeat -- top folder
    
    end tell

    Getting and playing with file sizes

    property Sizes : {}
    property PercentageOfTotalDataSize : {}
    
    global SmallestSize
    global LargestSize
    global TotalSize
    global AverageSize
    
    property SmallestFileName : ""
    property LargestFileName : ""
    
    set sourceFolder to choose folder
    
    set theItems to list folder sourceFolder without invisibles
    set itemCount to (get count of items in theItems)
    
    repeat with thisItem from 1 to itemCount
    	set theItem to item thisItem of theItems
    	set theItem to (sourceFolder & theItem) as string
    	set theItemInfo to info for (theItem as alias)
    	set theSize to size of theItemInfo
    	set end of Sizes to theSize
    
    	set theFileName to name of theItemInfo
    
    	if thisItem = 1 then
    
    		set SmallestSize to theSize
    		set SmallestFileName to theFileName
    		set LargestSize to theSize
    		set LargestFileName to theFileName
    		set TotalSize to theSize
    		set AverageSize to theSize
    
    	else
    
    		-- smallest
    		if theSize < SmallestSize then
    			set SmallestSize to theSize
    			set SmallestFileName to theFileName
    		end if
    
    		-- largest
    		if theSize > LargestSize then
    			set LargestSize to theSize
    			set LargestFileName to theFileName
    		end if
    
    		-- total
    		set TotalSize to TotalSize + theSize
    
    		-- average
    		set AverageSize to TotalSize / thisItem
    	end if
    
    end repeat
    
    set smallestSizeText to makeSizeHumanReadable(SmallestSize) of me
    set largestSizeText to makeSizeHumanReadable(LargestSize) of me
    set totalSizeText to makeSizeHumanReadable(TotalSize) of me
    set averageSizeText to makeSizeHumanReadable(AverageSize) of me
    
    repeat with thisSize from 1 to (get count of items in Sizes)
    	set end of PercentageOfTotalDataSize to (((item thisSize of Sizes) / TotalSize) * 100)
    end repeat
    
    on makeSizeHumanReadable(theSize)
    	if theSize ≥ 1000 * 1000 * 1000 then
    		return ((theSize / 1000 / 1000 / 1000) as string) & " GB"
    	else if (theSize < 1000 * 1000 * 1000) and (theSize ≥ 1000 * 1000) then
    		return ((theSize / 1000 / 1000) as string) & " MB"
    	else
    		return ((theSize / 1000) as string) & " KB"
    	end if
    end makeSizeHumanReadable

    Unlock all items in a dropped folder

    This is useful for preparing a large, deep, complex folder for trashing.

    on open theFolder
    	tell application "Finder"
    		(* Files *)
    		set owner privileges of files of entire contents of theFolder to read write
    		set group privileges of files of entire contents of theFolder to read write
    		set everyones privileges of files of entire contents of theFolder to read write
    		set locked of files of entire contents of theFolder to false
    		(* Folders *)
    		set owner privileges of folders of entire contents of theFolder to read write
    		set group privileges of folders of entire contents of theFolder to read write
    		set everyones privileges of folders of entire contents of theFolder to read write
    		set locked of folders of entire contents of theFolder to false
    		quit
    	end tell
    end open

    Track running time a script and report

    Very useful for keeping track of process times, especially for assessing the longer, complex scripts that might do with some optimization or porting to faster methods of automation.

    set startTime to (current date)
    (* Do something *)
    set endTime to (current date)
    set runTime to (endTime - startTime)
    display dialog runTime & " seconds."

    Compress folders by name and delete the original, droplet for multiple root folders at once.

    I work for a publishing company, and we receive archives that have been preflighted, meaning that each layout file has been collected and linked resources moved to Fonts and Images folders. Fonts for the Mac don’t play well on Windows servers, even through well-intentioned digital asset management systems. This was created to help ensure that fonts survive the archiving process.

    (*
    File: __File Name__
    Author(s): Philip Regan
    Source Code Copyright: Copyright (c) __Current Year__ Philip Regan All Rights Reserved.
    Additional Copyright: None __Client Copyright__ __Borrowed/Adapted Code Copyright__							
    Source:	New source only; no adaptations.
    Requirements: __Application Names__
    Notes:	
    
    ditto -c -k --sequesterRsrc --keepParent  .zip
    macpro-philipr:~ philipr$ 
    
    About the command string:
    
    ditto [options] src_file dst_file[.ext]
    
    -c
    Create an archive at the destination path.  The default
    format is CPIO, unless -k is given.  CPIO archives should
    be stored in files with names ending in .cpio.  Compressed
    CPIO archives should be stored in files with names ending
    in .cpgz.
    
    -k
    Create or extract from a PKZip archive instead of the
    default CPIO.  PKZip archives should be stored in filenames
    ending in .zip.
    
    --sequesterRsrc
    When creating a PKZip archive, preserve resource forks and
    HFS meta-data in the subdirectory __MACOSX.  PKZip extrac-
    tion will automatically find these resources.
    
    --keepParent
    When creating an archive, embed the parent directory name
    src in dst_archive.
    
    Actual command
    
    ditto -c -k --sequesterRsrc --keepParent /Users/philipr/Desktop/untitled\ folder/untitled\ folder/Fonts/ /Users/philipr/Desktop/untitled\ folder/untitled\ folder/Fonts.zip
    
    Note that spaces need to be escaped with "\ " before submitting to the shell otherwise the ditto command will return a "cannot process multiple sources" error.
    
    Change History:
    	10_08_23_01_01_000:	Started source
    
        YY_MM_DD_MM_mm_BUG: Started source
    *)
    
    property pFileList : {}
    
    on open of theFiles
    	with timeout of 86400 seconds
    		set lastFile to count theFiles
    		repeat with thisFile from 1 to lastFile
    			set theFile to item thisFile of theFiles
    			my SearchAndDestroy(theFile)
    		end repeat
    
    		display dialog "Done"
    
    	end timeout
    end open
    
    on run {}
    	with timeout of 86400 seconds
    
    		tell application "Finder"
    			set sourceFolder to choose folder with prompt "Please select directory."
    		end tell
    
    		my SearchAndDestroy(sourceFolder)
    
    		display dialog "Done"
    
    	end timeout
    end run
    
    on SearchAndDestroy(sourceFolder)
    	set pFileList to {}
    
    	with timeout of 86400 seconds --86400 seconds = 24 hours
    
    		my createList(sourceFolder)
    
    		set lastFolder to count pFileList
    		repeat with thisFolder from 1 to lastFolder
    			set theFolder to item thisFolder of pFileList
    			my CompressFolder(theFolder)
    			my DeleteFolder(theFolder)
    		end repeat
    
    	end timeout
    end SearchAndDestroy
    
    on CompressFolder(folderPath) -- (string) as void
    
    	set theFolder to folderPath as alias
    
    	set sourcePosix to (POSIX path of theFolder)
    	set sourcePosix to EscapeSpacesInPath(sourcePosix) of me
    
    	set destinationPosix to MakeZipPath(folderPath) of me
    
    	log "ditto -c -k --sequesterRsrc --keepParent " & sourcePosix & " " & destinationPosix
    	do shell script "ditto -c -k --sequesterRsrc --keepParent " & sourcePosix & " " & destinationPosix
    
    end CompressFolder
    
    on EscapeSpacesInPath(thePath) -- (string) as string
    	set theEscapedPath to replace_chars(thePath, " ", "\\ ")
    	return theEscapedPath
    end EscapeSpacesInPath
    
    on MakeZipPath(folderPath) -- (string) as string
    	set posixPath to (POSIX path of (folderPath as alias