Hi.
Sorry for the slow reply. As you can see below, getting ‘dates added’ isn’t quite the same as getting modification dates!
While modification dates are properties of disk items themselves, ‘dates added’ are information collected and stored by Spotlight. The only way I know to get them is with a shell script. The only way I know to interpret and use the results is with AppleScriptObjC. And if using AppleScriptObjC for that, it makes sense to use it for other things in the script too ” such as getting and moving the items, which it can do much faster than the Finder can. And that leads to several different ways of doing things, all of which require quite a lot of code! But it’s only the verbosity of the language. The execution is pretty fast.
I found in my testing that quite a few of my own files and folders don’t have ‘dates added’. Some are in folders that I’ve told Spotlight not to scan, but I think the others, which are several years old, have simply been in their folders since before Spotlight was invented! I don’t think this will affect you, but I’ve allowed for it just in case. At the moment, the script’s set up to move any items it finds which don’t have ‘dates added’, but you can change the movingWhenNoDateAdded value at the top to false to have them left alone.
Let me know if there are any problems.
Edit: Script modified to use Shane’s NSURLAddedToDirectoryDateKey suggestion in the post below, which removes the need for the shell script and thus for the set-up and interpretation in that respect. It’s still not short, but it’s shorter and slightly faster.
Edit 2: Further modified to use NSURLs throughout. There was a non-fatal but embarrassing mix-up of paths and URLs in the original modification!
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
(* Script configuration properties. Adjust as required. *)
-- The minimum number of days items must have been in the folder before they're moved.
property X : 2
-- How to interpret "days": "calendar days" [true] or "24-hour units from run time" [false]?
property daysMeansCalendarDays : true
-- What to do if an item has no 'date added': move it anyway [true] or not [false]?
property movingWhenNoDateAdded : true
-- What to do with any items already in "Anteriormente." which have the same names as items being moved: zap them [true] or move them to the trash [false]?
property zappingReplacedItems : true
(* Entry point for a "Run AppleScript" Automator action. *)
on run {input, parameters}
return moveOldItems(input)
end run
(* Main handler. *)
on moveOldItems(input)
set |⌘| to current application
-- Use one of the items which triggered the folder action to identify the folder.
set sample to item 1 of input
set sampleURL to |⌘|'s class "NSURL"'s fileURLWithPath:(POSIX path of sample)
set folderURL to sampleURL's URLByDeletingLastPathComponent()
-- Before doing anything else, check that an "Anteriormente." folder exists in the folder. If not, show a message and return the script's input.
set AnteriormenteURL to folderURL's URLByAppendingPathComponent:("Anteriormente.")
if ((AnteriormenteURL's checkResourceIsReachableAndReturnError:(missing value)) as boolean) then
if ((AnteriormenteURL's resourceValuesForKeys:({|⌘|'s NSURLIsDirectoryKey, |⌘|'s NSURLIsPackageKey}) |error|:(missing value)) as record is not {NSURLIsDirectoryKey:true, NSURLIsPackageKey:false}) then
display dialog "The item \"Anteriormente.\" isn't a folder!"
return input
end if
else
display dialog "The folder \"Anteriormente.\" doesn't exist in this folder!"
return input
end if
-- Get NSURLs to every visible item in the folder and include their 'dates added'.
set fileManager to |⌘|'s class "NSFileManager"'s defaultManager()
set dateAddedKey to |⌘|'s NSURLAddedToDirectoryDateKey
set contentURLs to (fileManager's contentsOfDirectoryAtURL:(folderURL) includingPropertiesForKeys:({dateAddedKey}) options:(|⌘|'s NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value))
-- Filter out URLs to items named "Anteriormente." or "NO GUARDAR"
set nameFilter to |⌘|'s class "NSPredicate"'s predicateWithFormat:("NOT lastPathComponent IN %@") argumentArray:({{"Anteriormente.", "NO GUARDAR"}})
set filteredURLs to contentURLs's filteredArrayUsingPredicate:(nameFilter)
-- Set up the cut-off date with which to compare the 'dates added'.
set XDaysAgo to |⌘|'s class "NSDate"'s dateWithTimeIntervalSinceNow:(-X * days)
if (daysMeansCalendarDays) then set XDaysAgo to |⌘|'s class "NSCalendar"'s currentCalendar()'s startOfDayForDate:(XDaysAgo)
-- Deal with each of the URLs in turn.
set output to {} -- For aliases to the moved items.
repeat with thisURL in filteredURLs
-- Get this item's 'date added', if any.
set {noProblem, dateAdded} to (thisURL's getResourceValue:(reference) forKey:(dateAddedKey) |error|:(missing value))
if (noProblem) then
if (dateAdded is missing value) then
-- No 'date added'. Move the item to the "Anteriormente." folder if the script's configured to do so in this situation.
if (movingWhenNoDateAdded) then set end of output to moveItem(fileManager, thisURL, AnteriormenteURL)
else
-- Otherwise move the item if the date added is earlier than the cutoff date.
if ((dateAdded's timeIntervalSinceDate:(XDaysAgo)) < 0) then set end of output to moveItem(fileManager, thisURL, AnteriormenteURL)
end if
end if
end repeat
return output
end moveOldItems
(* Move an item to another folder, keeping its original name. Return an alias to the result. *)
on moveItem(fileManager, sourceURL, destinationFolderURL)
set destinationURL to destinationFolderURL's URLByAppendingPathComponent:(sourceURL's lastPathComponent)
-- If an item with the same name already exists in the target folder, zap it or move it to the trash according to the script's configuration settings.
if ((destinationURL's checkResourceIsReachableAndReturnError:(missing value)) as boolean) then
if (zappingReplacedItems) then
fileManager's removeItemAtURL:(destinationURL) |error|:(missing value)
else
fileManager's trashItemAtURL:(destinationURL) resultingItemURL:(missing value) |error|:(missing value)
end if
end if
-- Move the item.
fileManager's moveItemAtURL:(sourceURL) toURL:(destinationURL) |error|:(missing value)
return destinationURL's |path|() as string as POSIX file as alias
end moveItem