Recursively Find last modified file

the POSIX path property of an alias exists at least since Panther (10.3).
I’m using it all the time without any problems

Hello.

You are right, I can make it work too. I had a different name for my project folder, which I believe was the culprit after all. (Non existing alias, but the error message I got was about making an alias of a list. )

Is there some reason you used this rather an Automator service? It just seems a more heavyweight solution, and an Automator-based solution should be more contextual.

But it seems much slower than using the count command:

set x to {"a"}
repeat 12 times
	set x to x & x
end repeat

tell application id "au.com.myriad-com.ASObjC-Runner" -- ASObjC Runner.app
	set t1 to elapsed time
	repeat 1000 times
		length of x
	end repeat
	set t2 to elapsed time
	repeat 1000 times
		count x
	end repeat
	set t3 to elapsed time
	return format number {t2 - t1, t3 - t2} format "0.000"
end tell

I like that you can quickly package the service to distribute with icons, a Read Me, etc. Someone also explained to me that it was faster. I don’t know the inner workings of either solution. What do you think? Does either option provide an advantage/disadvantage ?

Right. The test script returns:
{“0,123”, – with length
“0,001” – with count
}

So, I will have to continue to use count or count of which is safer when I write scripts.

This kind of forum is wonderful ” I learn things quite every time I try to help somebody.

Yvan KOENIG (VALLAURIS, France) dimanche 31 mars 2013 17:07:10

Hi Shane,
Regarding your script at #15, I noticed that the ASObjC Runner can’t get the current date, passing it to the current app with the non-fatal error −10004. So, I moved it out of the tell block:

set target to (path to documents folder as text) & "test:"
set CurrentDate to (current date)
tell application "ASObjC Runner"
	set longList to enumerate folder target modified before {false, CurrentDate - 90 * days} with recursion
	set pathsAndDates to (about file longList include only {"POSIX path", "modification date"})
	set begOfList to rearrange records pathsAndDates by keys {"«asmo»"} without ascending orders -- asmo = modification date
	set fileList to value for label "«posx»" in records begOfList -- posx = POSIX path
	if length of fileList > 10 then set fileList to items 1 thru 10 of fileList
end tell

Regarding the usage of “length of fileList > 10” or “(count of fileList) > 10”, your comment and example at #24 clearly shows a very big timing difference in favour of “count”. Running your example I get → {“0.198”, “0.001”}. However, if I run the two forms in your original script:

set target to (path to documents folder as text) & "test:"
set CurrentDate to (current date)
tell application "ASObjC Runner"
	set longList to enumerate folder target modified before {false, CurrentDate - 90 * days} with recursion
	set pathsAndDates to (about file longList include only {"POSIX path", "modification date"})
	set begOfList to rearrange records pathsAndDates by keys {"«asmo»"} without ascending orders -- asmo = modification date
	set fileList to value for label "«posx»" in records begOfList -- posx = POSIX path
	set t1 to elapsed time
	if length of fileList > 10 then set fileList to items 1 thru 10 of fileList
	set t2 to elapsed time
	if (count of fileList) > 10 then set fileList to items 1 thru 10 of fileList
	set t3 to elapsed time
	return format number {t2 - t1, t3 - t2} format "0.000000" --> {"0.000485", "0.000418"}
end tell

the timing difference is insignificant. Could you explain why?
BTW, my test folder contains 147 files and I have the current ASObjC Runner 1.9.10 and ML 10.8.3.

Cheers, Chris

In post #24, ‘length’ and ‘count’ count 4096 items 1000 times each. However many items are counted in your script, ‘length’ and ‘count’ only count them once each and ‘count’ counts at most ten of them and doesn’t create a new list within the timed period. :slight_smile:

Sorry, my mistake to use the reduced list for “count”. Here are the corrected values:

set target to (path to documents folder as text) & "test:"
set CurrentDate to (current date)
tell application "ASObjC Runner"
	set longList to enumerate folder target modified before {false, CurrentDate - 90 * days} with recursion
	set pathsAndDates to (about file longList include only {"POSIX path", "modification date"})
	set begOfList to rearrange records pathsAndDates by keys {"«asmo»"} without ascending orders -- asmo = modification date
	set fileList to value for label "«posx»" in records begOfList -- posx = POSIX path
	display dialog (count of fileList) as text --> "147"
	set t1 to elapsed time
	if length of fileList > 10 then set fileList_length to items 1 thru 10 of fileList
	set t2 to elapsed time
	if (count of fileList) > 10 then set fileList_count to items 1 thru 10 of fileList
	set t3 to elapsed time
	return format number {t2 - t1, t3 - t2} format "0.000000" --> {"0.001024", "0.000519"}
end tell

Using the same original fileList the timing difference is indeed significant. So, “count” is the way to go.

Thanks,
Chris

I don’t know much about ThisService (it behaves a bit oddly here), but using Automator you have the service show only in the Finder, and only if a folder (or folders) is/are selected. As far as I can tell, ThisService only has input options for text selections. But I may be misunderstanding.

It seems to me that ThisService was a great option before Automator got the ability to build services, but no, not so much.

Yes, current date is a scripting addition command, and apart from a couple of exceptions, you can’t call them in any app tell block – AS handles it via the silent non-fatal error and redirection you’re seeing. I should have moved it outside, as Yvan’s code off-list did.

Yes and no :slight_smile:

If you’re only doing it once or twice, the difference is neither here nor there. And if you’re counting big lists regularly, chances are you’re looping through them, in which case the counting time will probably be lost in the noise. So I’m not sure it matters much.

But intuitively I would have suspected a property would be quicker than a command. Which again goes to show how pointless it is to judge the speed of code any way but timing it.

FWIW, there was some reason behind my intuition. The timer I added to ASObjC Runner is very simple: a single Objective-C call of + timeIntervalSinceReferenceDate. There are more precise ways, but in the contents of AS and all the overhead it adds, this looked good enough.

The question was which was the most efficient way to implement it: as a property or a command. In this case, testing showed a property was a bit quicker (not by the sort of margin in count vs length of a list, mind you), so that’s what I went with.

It still takes time though:

tell application id "au.com.myriad-com.ASObjC-Runner" -- ASObjC Runner.app
	set n to 1000 -- times to test
	set t1 to elapsed time
	repeat n - 1 times
		elapsed time
	end repeat
	set t2 to elapsed time
	set x to format number (t2 - t1) / n format "0.00000"
end tell
display dialog x

And the result will vary, depending on how you run it…

If you go back to your script in post #24 and change ‘length of x’ to ‘length of my x’ and ‘count x’ to ‘count my x’, you’ll find the timings almost identical.

Yes, it’s that oddity again.