I have two scripts (originated here on MacScripter) as follows:
set theFolder to "MacBook HD:Users:homer:Documents:" as alias -- change path to desired value
set foldersAndFiles to getFoldersAndFiles(theFolder)
writeFile(foldersAndFiles)
on getFoldersAndFiles(theFolder)
set foldersAndFiles to {theFolder as text}
tell application "Finder"
set theFiles to (name of every file in theFolder)
if theFiles ≠ {} then set the end of foldersAndFiles to theFiles
try
set theFolders to (every folder of the entire contents of theFolder) as alias list
on error
set theFolders to {}
end try
repeat with aFolder in theFolders
set contents of aFolder to aFolder as text
end repeat
set theFolders to sortFolders(theFolders) of me
repeat with aFolder in theFolders
set end of foldersAndFiles to linefeed & aFolder
set theFiles to name of every file in folder aFolder
if theFiles ≠ {} then set the end of foldersAndFiles to theFiles
end repeat
end tell
set {ATID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, linefeed}
set foldersAndFiles to foldersAndFiles as text
set AppleScript's text item delimiters to ATID
return foldersAndFiles
end getFoldersAndFiles
on writeFile(theText)
set pdfMargins to 25
set targetTextFile to (path to temporary items as text) & "MacBook Pro Documents.txt"
set targetPdfFile to (path to desktop as text) & "MacBook Pro Documents.pdf"
try
set openedFile to (open for access file targetTextFile with write permission)
set eof of openedFile to 0
write theText to openedFile starting at eof
close access openedFile
on error
try
close access file targetTextFile
end try
end try
do shell script "cupsfilter -D -o page-left=" & pdfMargins & " -o page-right=" & pdfMargins & " -o page-top=" & pdfMargins & " -o page-bottom=" & pdfMargins & " " & quoted form of POSIX path of targetTextFile & " > " & quoted form of POSIX path of targetPdfFile
end writeFile
on sortFolders(a)
repeat with i from (count a) to 2 by -1
repeat with j from 1 to i - 1
if item j of a > item (j + 1) of a then
set {item j of a, item (j + 1) of a} to {item (j + 1) of a, item j of a}
end if
end repeat
end repeat
return a
end sortFolders
And the second:
use framework "Foundation"
use scripting additions
set theFolder to "/Users/homer/Documents"
set theDays to 3
set theFiles to getFiles(theFolder, theDays)
set theFiles to formatFiles(theFiles) -- disable if desired
writeFile(theFiles)
on getFiles(theFolder, theDays)
set fileManager to current application's NSFileManager's defaultManager()
set theFolder to current application's |NSURL|'s fileURLWithPath:theFolder
set dateKey to current application's NSURLContentModificationDateKey
set regularFileKey to (current application's NSURLIsRegularFileKey) -- does not include packages
set folderContents to (fileManager's enumeratorAtURL:theFolder includingPropertiesForKeys:{} options:6 errorHandler:(missing value))'s allObjects() -- excludes hidden files and package contents
set filterDate to current application's NSDate's dateWithTimeIntervalSinceNow:(-86400 * theDays)
set theFiles to current application's NSMutableArray's new()
repeat with anItem in folderContents
set {theResult, aDate} to (anItem's getResourceValue:(reference) forKey:dateKey |error|:(missing value))
if (aDate's compare:filterDate) = 1 then -- use -1 to return older files
set {theResult, aRegularFile} to (anItem's getResourceValue:(reference) forKey:regularFileKey |error|:(missing value))
if aRegularFile as boolean is true then (theFiles's addObject:anItem)
end if
end repeat
if theFiles's |count|() = 0 then display dialog "No matching files found" buttons {"OK"} cancel button 1
set pathDescriptor to current application's NSSortDescriptor's sortDescriptorWithKey:"stringByDeletingLastPathComponent" ascending:true selector:"localizedStandardCompare:" -- sort by path of containing folder
set nameDescriptor to current application's NSSortDescriptor's sortDescriptorWithKey:"lastPathComponent" ascending:true selector:"localizedStandardCompare:" -- sort by file name
return ((theFiles's valueForKey:"path")'s sortedArrayUsingDescriptors:{pathDescriptor, nameDescriptor})
end getFiles
on formatFiles(theFiles)
set filePaths to theFiles's valueForKey:"stringByDeletingLastPathComponent"
set fileNames to theFiles's valueForKey:"lastPathComponent"
set formattedFiles to current application's NSMutableArray's arrayWithArray:{filePaths's objectAtIndex:0, fileNames's objectAtIndex:0}
set oldFilePath to filePaths's objectAtIndex:0
repeat with i from 1 to ((theFiles's |count|()) - 1)
if ((filePaths's objectAtIndex:i)'s isEqualToString:oldFilePath) as boolean is false then
(formattedFiles's addObjectsFromArray:{"", filePaths's objectAtIndex:i, fileNames's objectAtIndex:i})
else
(formattedFiles's addObject:(fileNames's objectAtIndex:i))
end if
set oldFilePath to (filePaths's objectAtIndex:i)
end repeat
return formattedFiles
end formatFiles
on writeFile(theFiles)
set theString to theFiles's componentsJoinedByString:linefeed
set theFolder to (current application's NSHomeDirectory()'s stringByAppendingPathComponent:"Desktop")
set theFile to theFolder's stringByAppendingPathComponent:"Recent Documents.txt"
theString's writeToFile:theFile atomically:true encoding:(current application's NSUTF8StringEncoding) |error|:(missing value)
end writeFile
I have tried changing the text producing script to a PDF producing script for the last couple of days, with no luck. And, my AppleScript skills are poor, so I have little idea how to do this other than cut & paste. Any help would be appreciated.
Homer. There were two issues. The variable theFiles needed to be made into a string. Also, the code in the writeFile handler that created a temporary file would not work. I don’t know the reason for that, so I substituted ASObjC code. The resulting script worked in limited testing on my Sonoma computer.
This script needs another look, and I’ll do that in a day or so. In the meantime, let me know of any issues.
use framework "Foundation"
use scripting additions
set theFolder to "/Users/Robert/Documents/" --set to desired value
set theDays to 30 --set to desired value
set theFiles to getFiles(theFolder, theDays)
set theFiles to formatFiles(theFiles) -- disable if desired
set theFiles to ((theFiles's componentsJoinedByString:linefeed) as text)
writeFile(theFiles)
on getFiles(theFolder, theDays)
set fileManager to current application's NSFileManager's defaultManager()
set theFolder to current application's |NSURL|'s fileURLWithPath:theFolder
set dateKey to current application's NSURLContentModificationDateKey
set regularFileKey to (current application's NSURLIsRegularFileKey) -- does not include packages
set folderContents to (fileManager's enumeratorAtURL:theFolder includingPropertiesForKeys:{} options:6 errorHandler:(missing value))'s allObjects() -- excludes hidden files and package contents
set filterDate to current application's NSDate's dateWithTimeIntervalSinceNow:(-86400 * theDays)
set theFiles to current application's NSMutableArray's new()
repeat with anItem in folderContents
set {theResult, aDate} to (anItem's getResourceValue:(reference) forKey:dateKey |error|:(missing value))
if (aDate's compare:filterDate) = 1 then -- use -1 to return older files
set {theResult, aRegularFile} to (anItem's getResourceValue:(reference) forKey:regularFileKey |error|:(missing value))
if aRegularFile as boolean is true then (theFiles's addObject:anItem)
end if
end repeat
if theFiles's |count|() = 0 then display dialog "No matching files found" buttons {"OK"} cancel button 1
set pathDescriptor to current application's NSSortDescriptor's sortDescriptorWithKey:"stringByDeletingLastPathComponent" ascending:true selector:"localizedStandardCompare:" -- sort by path of containing folder
set nameDescriptor to current application's NSSortDescriptor's sortDescriptorWithKey:"lastPathComponent" ascending:true selector:"localizedStandardCompare:" -- sort by file name
return ((theFiles's valueForKey:"path")'s sortedArrayUsingDescriptors:{pathDescriptor, nameDescriptor})
end getFiles
on formatFiles(theFiles)
set filePaths to theFiles's valueForKey:"stringByDeletingLastPathComponent"
set fileNames to theFiles's valueForKey:"lastPathComponent"
set formattedFiles to current application's NSMutableArray's arrayWithArray:{filePaths's objectAtIndex:0, fileNames's objectAtIndex:0}
set oldFilePath to filePaths's objectAtIndex:0
repeat with i from 1 to ((theFiles's |count|()) - 1)
if ((filePaths's objectAtIndex:i)'s isEqualToString:oldFilePath) as boolean is false then
(formattedFiles's addObjectsFromArray:{"", filePaths's objectAtIndex:i, fileNames's objectAtIndex:i})
else
(formattedFiles's addObject:(fileNames's objectAtIndex:i))
end if
set oldFilePath to (filePaths's objectAtIndex:i)
end repeat
return formattedFiles
end formatFiles
on writeFile(theText)
set pdfMargins to 25
set targetPdfFile to (path to desktop as text) & "Folder Contents.pdf"
set targetTextFile to (current application's NSTemporaryDirectory())'s stringByAppendingPathComponent:"Folder Contents.txt"
(current application's NSString's stringWithString:theText)'s writeToFile:targetTextFile atomically:true encoding:(current application's NSUTF8StringEncoding) |error|:(missing value)
set targetTextFile to targetTextFile as text
do shell script "cupsfilter -D -o page-left=" & pdfMargins & " -o page-right=" & pdfMargins & " -o page-top=" & pdfMargins & " -o page-bottom=" & pdfMargins & " " & quoted form of POSIX path of targetTextFile & " > " & quoted form of POSIX path of targetPdfFile
end writeFile
For two days, I tried everything I could think of before finally posting here. And based on the two issues you mentioned, I really didn’t (with my limited skills) stand a chance. I also tried using the Shortcut you posted here that converts a file to a PDF.
In any event, this script works perfectly. Thank you again.
I edited my script to correct a few issues. The only substantive change is that packages are now returned along with files. The timing result when run on my home folder ranged from 140 to 170 milliseconds, with the difference attributable to the value of the theDays variable (the greater the value the longer the timing result).
use framework "Foundation"
use scripting additions
on main()
set theFolder to POSIX path of (choose folder)
set theDays to 7 --set to desired value
set theFiles to getFiles(theFolder, theDays)
set folderTree to getFolderTree(theFiles)
writeFile(folderTree)
end main
on getFiles(theFolder, theDays)
set fileManager to current application's NSFileManager's defaultManager()
set theFolder to current application's |NSURL|'s fileURLWithPath:theFolder
set dateKey to current application's NSURLContentModificationDateKey
set directoryKey to current application's NSURLIsDirectoryKey
set packageKey to current application's NSURLIsPackageKey
set folderContents to (fileManager's enumeratorAtURL:theFolder includingPropertiesForKeys:{} options:6 errorHandler:(missing value))'s allObjects() --option 6 skips hidden files and package contents
set filterDate to current application's NSDate's dateWithTimeIntervalSinceNow:(-86400 * theDays)
set theFiles to current application's NSMutableArray's new()
repeat with anItem in folderContents
set {theResult, aDate} to (anItem's getResourceValue:(reference) forKey:dateKey |error|:(missing value))
if (aDate's compare:filterDate) = 1 then --1 is NSOrderedDescending
set {theResult, aDirectory} to (anItem's getResourceValue:(reference) forKey:directoryKey |error|:(missing value))
if (aDirectory as boolean) is false then
(theFiles's addObject:anItem)
else
set {theResult, aPackage} to (anItem's getResourceValue:(reference) forKey:packageKey |error|:(missing value))
if (aPackage as boolean) is true then (theFiles's addObject:anItem)
end if
end if
end repeat
if theFiles's |count|() = 0 then display dialog "No matching files found" buttons {"OK"} cancel button 1
set pathDescriptor to current application's NSSortDescriptor's sortDescriptorWithKey:"stringByDeletingLastPathComponent" ascending:true selector:"localizedStandardCompare:"
set nameDescriptor to current application's NSSortDescriptor's sortDescriptorWithKey:"lastPathComponent" ascending:true selector:"localizedStandardCompare:"
return ((theFiles's valueForKey:"path")'s sortedArrayUsingDescriptors:{pathDescriptor, nameDescriptor})
end getFiles
on getFolderTree(theFiles)
set fileTree to current application's NSMutableArray's new()
set previousFolder to (theFiles's objectAtIndex:0)'s stringByDeletingLastPathComponent()
fileTree's addObject:(previousFolder's stringByAppendingString:"/")
repeat with aFile in theFiles
set aFolder to aFile's stringByDeletingLastPathComponent()
set aFileName to aFile's lastPathComponent()
if (aFolder's isEqualToString:previousFolder) is false then
(fileTree's addObject:"")
(fileTree's addObject:(aFolder's stringByAppendingString:"/"))
(fileTree's addObject:aFileName)
else
(fileTree's addObject:aFileName)
end if
set previousFolder to aFolder
end repeat
return ((fileTree's componentsJoinedByString:linefeed) as text)
end getFolderTree
on writeFile(theText)
set pdfMargins to 25
set targetTextFile to ((current application's NSTemporaryDirectory())'s stringByAppendingPathComponent:"Folder Contents.txt") as text
set targetPdfFile to (((current application's NSHomeDirectory())'s stringByAppendingPathComponent:"Desktop")'s stringByAppendingPathComponent:"Folder Contents.pdf") as text
(current application's NSString's stringWithString:theText)'s writeToFile:targetTextFile atomically:true encoding:(current application's NSUTF8StringEncoding) |error|:(missing value)
do shell script "cupsfilter -D -o page-left=" & pdfMargins & " -o page-right=" & pdfMargins & " -o page-top=" & pdfMargins & " -o page-bottom=" & pdfMargins & " " & quoted form of targetTextFile & " > " & quoted form of targetPdfFile
end writeFile
main()
I’m sure there are other changes, but this is the first one I’ve spotted:
on main()
set theFolder to POSIX path of (choose folder)
set theDays to 7 --set to desired value
set theFiles to getFiles(theFolder, theDays)
set folderTree to getFolderTree(theFiles)
writeFile(folderTree)
end main
Which seems to work equally well when formatted both ways below.
This:
on main()
set theFolder to POSIX path of "/Users/homer/Documents/" --set to desired value
set theDays to 7 --set to desired value
set theFiles to getFiles(theFolder, theDays)
set folderTree to getFolderTree(theFiles)
writeFile(folderTree)
end main
And this:
set theFolder to "/Users/homer/Documents/" --set to desired value
set theDays to 7 --set to desired value
set theFiles to getFiles(theFolder, theDays)
set folderTree to getFolderTree(theFiles)
writeFile(folderTree)
end main
Is there a reason one would leave the “to POSIX path of” in the script?
“/Users/homer/Documents/” is already a POSIX path, so there’s no need to include “to POSIX path of” in the script. The second alternative is the correct one.