Mysteriously working script [Finder]

Every have one of those moments when you write a script and mid-testing it suddenly seems to work? Here’s one from today…


property validFileTypes : {"JPEG Image", "PDF Document"} -- Not a fan of using kind but I was going to respond to someone on the Adobe boards.

on open input_folder
	set fileList to {}
	tell application "Finder"
		repeat with i in (item 1 of input_folder) -- ******* Here's where the magic starts... *******
			set fileKind to kind of i
			 display dialog "" & i & return & return & "Kind: " & fileKind 
			if kind of i is in validFileTypes then
				-- ******* Set fileList to fileList & i -- DOESN'T WORK. WHY?? *******
				copy i to end of fileList -- ******* Copying it does ????? *******
			end if
		end repeat
		if fileList ≠ {} then open fileList
	end tell
end open

So… You drop a folder on this. It returns a single item list with the folder as an alias. Until today, I would have requested a list of file/items of input_folder. Here the repeat loop picks them up automatically BECAUSE IT’S IN THE FINDER BLOCK. Move the repeat outside the Finder block and you’ll get an error that “item 1 of … doesn’t understand the COUNT message”! Not earth shattering, I know, but interesting.

If anyone knows, though… I’m curious as to why the set method doesn’t work for building the filelist, but the copy method does. Nigel, Bruce, Adam, JJ, anyone ???

Jim Neumann
BLUEFROG

On my box, BF, a jpeg file shows its kind as “JPEG Document”. (Tiger latest)

This works for me:

property vft : {"JPEG Document", "PDF Document"}
set f to choose folder
set af to {}
tell application "Finder"
	set fs to every file in f as alias list
	repeat with aFile in fs
		if kind of (info for aFile) is in vft then set end of af to name of (info for aFile)
	end repeat
end tell

Adam:

Yeah, it’s JPEG Image on 10.3.9.

BTW, it’s not that the script doesn’t work – it does. I was just surprised that it did. Putting the repeat loop within the Finder block gave me an unexpected (but very welcome) surprise.

My question is about the building of the filelist.

set fileList to fileList & i came up with “unexpected object type” but copy i to end of filelist worked. I’m wondering if anyone knows why.

Jim

I understood, Jim, but couldn’t test. It doesn’t work in Tiger in either form and I don’t have 10.3 up and running.

Interesting that it’s Panther only. Weird.

Have a good weekend,Adam.

Jim

Hi, Jim.

I’m not totally sure, but here are a few thoughts. In that kind of repeat, ‘i’ isn’t an item in its own right, but a reference to it in the context of whatever its ‘in’. So in your script, the first two values of i would be something like:

item 1 of item 1 of {alias "My disk:My path:This folder:"} item 2 of item 1 of {alias "My disk:My path:This folder:"} --etc.
These references are a bit complex, because the first ‘item’ mentioned in them is a Finder ‘item’ (something in the folder) and the second is an AppleScript ‘item’ (something in the list).

What normally happens when something is concatenated to a list, is that if that something isn’t a list itself, it’s coerced to one. Normally, that means to a single-item list. The two lists then become the sources for a third list which is the result of “concatenating” them together. For some reason, there’s a problem coercing your complex references to lists, so the concatenations can’t go ahead. But if you present each reference as a single item list, the concatenation works. (In Tiger, at least.)

fileList to fileList & {i} -- i in a list

PS. With regard to your discussion with Adam, I am seeing your effects withTiger.

Strictly speaking, it’s not the ‘set’ or ‘copy’ methods that either work or don’t, but the “list concatenation” and “list extension” methods. You can use ‘set’ or ‘copy’ with either of them. Since you don’t actually need duplicates of the data, there’s no reason to use anything other than ‘set’:

set end of fileList to i

Running it again, Nigel, it did work. Don’t know how I screwed it up before. (Tiger 10.4.6). Thanks for the expanation.

While in the process of posting an answer to this earlier, I noticed that Mr G. had just beaten me to it - so I pulled mine, not wishing to duplicate. On reflection, though, I don’t suppose it does any harm…

I believe it might go something like this, Jim:

Since the variable input_folder represents a single-item list, {alias “path:to:some:folder”}, item 1 of that list would be: alias “path:to:some:folder”.

The repeat with i in some_list form iterates through a list of references (such as: item 1 of some_list, item 2 of some_list, item 3 of some_list, etc). Where some_list is not actually a list, an attempt is still made to iterate through (an implicit) items of some_list. (An expression like repeat with char in “some string”, for example, works in a similar way.)

So, at the beginning of the repeat loop, Finder interprets the repeat statement as:

Since the variable representing i is a reference to a reference, it will look (on each iteration) something like:

The issue arises because of differences between adding items to a list and concatenating items.

When a reference is added to a list, it can remain in reference form:

set l to {}
set l's end to a reference to item 3 of "some text"
l --> {item 3 of "some text"}

Concatenation usually causes references to be evaluated (presumably to determine the class of referenced items, so that the appropriate type of concatenation operation may be performed):

set l to {}
set l to l & (a reference to item 3 of "some text")
l --> {"m"}

However, if a reference is already wrapped in a class that can be readily concatenated, such as a list or record, no evaluation is performed:

set l to {}
set l to l & {a reference to item 3 of "some text"}
l --> {item 3 of "some text"}
set l to {}
set l to l & {my_ref:a reference to item 3 of "some text"}
l --> {my_ref:item 3 of "some text"}

So, in your script, concatenation forces a premature evaluation of the reference - and, since AppleScript (which performs the operation) doesn’t understand Finder objects, an Apple Event Manager error number -1731 [errAEUnknownObjectType] occurs.

In contrast, when adding items to a list (using either the set or the copy command), evaluation is deferred - and so the final representation of fileList might look something like:

Once the repeat loop has been exited, Finder is sent a command to open the list fileList - which it would evaluate as:

And since that makes sense to Finder, the relevant items are opened accordingly.

(A rather tortuous interpretation, but I hope it makes some sense. :))

As should:

on open input_folder tell application "Finder" to open (files of input_folder's item 1 whose kind is in validFileTypes) end open

I think you originally beat me by about a minute and a half, Mr E. Your post appeared above mine when I finally clicked the “Submit” button. I’m glad you reinstated it. Having another explanation here that’s vaguely similar to my own makes me more confident. :wink:

Yeah - I pulled it briefly to make a last-minute tweak - and you managed to sneak in during the intervening minute or so. Funny, I’d been wondering if the subject might have attracted your interest. :wink:

A feeling that is heartily reciprocated here, Mr G. :lol:

My many (and humble) thanks to all who responded. Y’know it’s funny… when you’re in environments where you are one of very few (if any) who understand AS, you’re the star of the show. But then I talk to you guys and realize what a hack I really am! (Albeit a darn good one! :P)

Once again, thanks for the lessons. This is what I love about this place.

Humbly,
Jim Neumann
BLUEFROG