On 2 Oct 2015, at 5:40 PM, Christopher Stone <email@hidden> wrote:
I expect there's an ASObjC method of doing this that is quite fast.
Your "this" seems to be a moving target ;-)
OK, step one is to get a list of the files. There are two main options: a simpler one that takes a POSIX path, and a slightly more complex one that takes an NSURL. However, the latter returns URLS, whereas the former returns just names, and it lets you filter out invisible items. Moreover, if you're running 10.11, you can just pass an alias or file and it will be bridged to a URL. So:
use AppleScript version "2.4" use scripting additions use framework "Foundation"
set theDesktop to path to desktop considering numeric strings if AppleScript's version < "2.5" then set theDesktop to current application's class "NSURL"'s fileURLWithPath:(POSIX path of theDesktop) end considering set fileManager to current application's NSFileManager's defaultManager() set theURLs to fileManager's contentsOfDirectoryAtURL:theDesktop includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
That gives you all the files, and will run on 10.10 too (or 10.9 within a script library). Extracting the ones you want can be done a couple of ways, depending on how you're filtering them. If it's based on the name ot path, you can do it very quickly with a predicate, which is a sort of whose clause for arrays. So for example:
set theDesktop to path to desktop considering numeric strings if AppleScript's version < "2.5" then set theDesktop to current application's class "NSURL"'s fileURLWithPath:(POSIX path of theDesktop) end considering set fileManager to current application's NSFileManager's defaultManager() set theURLs to fileManager's contentsOfDirectoryAtURL:theDesktop includingPropertiesForKeys:{} options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value) set extensionList to {"pdf", "txt", "scptd"} set exclusionList to {"Access.txt"} set thePredicate to current application's NSPredicate's predicateWithFormat:"(pathExtension IN [c]%@) AND (NOT lastPathComponent IN [c]%@)" argumentArray:{extensionList, exclusionList} set theURLs to theURLs's filteredArrayUsingPredicate:thePredicate
The [c] means to ignore case, and pathExtension and lastPathComponent are NSURL methods.
If you want to filter further, such as by label index, you need to loop through. So let's say you want only those left whose label index is in {2, 6, 7}. You need to get the value for the key NSURLLabelNumberKey. This relies on something in Objective-C that doesn't translate directly to AppleScript, so the workaround is to pass the value reference to the argument, which in turn tells AppleScript to return the result as a list, with the argument value included after the normal result. So:
set newArray to current application's NSMutableArray's array() -- to store URLs set theCount to theURLs's |count|() repeat with i from 1 to theCount set oneURL to (theURLs's objectAtIndex:(i - 1)) -- zero-based indexes set {theResult, theValue} to (oneURL's getResourceValue:(reference) forKey:(current application's NSURLLabelNumberKey) |error|:(missing value)) if theResult as boolean and {2, 6, 7} contains theValue then (newArray's addObject:oneURL) end if end repeat
Back where you got the contents of the directory, it can be a little more efficient if includingPropertiesForKeys: contains any properties you will be using, so you might also insert current application's NSURLLabelNumberKey in that empty list (although in this case the difference will probably be un-noticable).
Now you have an array of URLs. If you coerce it to a list in 10.11, you will get a list of POSIX paths; that's why the looping above was done using the Cocoa objectAtIndex: method, rather than "item i of ".
To move them, you just need another repeat loop and a destination:
set theDestURL to current application's class "NSURL"'s fileURLWithPath:somePosixPath set theCount to newArray's |count|() repeat with i from 1 to theCount set oneURL to (newArray's objectAtIndex:(i - 1)) -- zero-based indexes set theName to oneURL's lastPathComponent() (fileManager's moveItemAtURL:oneURL toURL:(theDestURL's URLByAppendingPathComponent:theName) |error|:(missing value)) end repeat
For your date string, you can use a date formatter. This is very simple under 10.11:
set theFormatter to current application's NSDateFormatter's new() theFormatter's setDateFormat:"yyyy MM dd hh.mm" set dateString to (theFormatter's stringFromDate:(current date)) as text
Under earlier versions, you need to convert the AS date to a Cocoa date, something like this:
on makeNSDateFrom:theASDate set {theYear, theMonth, theDay, theSeconds} to theASDate's {year, month, day, time} if theYear < 0 then set theYear to -theYear set theCalendar to current application's NSCalendar's currentCalendar() set newDate to theCalendar's dateWithEra:(theYear ≥ 0) |year|:theYear |month|:(theMonth as integer) |day|:theDay hour:0 minute:0 |second|:theSeconds nanosecond:0 return newDate end makeNSDateFrom:
Put all that together along with file manager's createDirectoryAtURL:withIntermediateDirectories:attributes:error:, and you're well on your way.
Or use the BridgePlus script library, and it's even easier...
|