Process one list by use of another

Need help with this one. I’ve trying to figure this out for about two weeks.

I have a list of files taken from a text doc example:
{“1.jpg”,“12.jpg”,“30.jpg”,“48.jpg”,“55.jpg”,“60.jpg”,“70.jpg”}

I have a list from every file in a folder example:
{“1.jpg” thru “100.jpg”}

I want to use the first list and use those items to duplicate a file in the second list to predetermined folder. Here it is, but it does’nt work.

with timeout of 600 seconds
	--GET TEXT DOC INTO LIST FORM FOR COMPARISON TO FOLDER FILES
	set aFile to (choose file with prompt "Select a file to read:" without invisibles)
	open for access aFile
	set txt to (read aFile)
	close access aFile
	
	set mylist_1 to {}
	set para to paragraphs of txt
	
	--Copy Text file to new list
	repeat with aP in para
		if (count aP) ≠ 0 then copy aP to end of mylist_1
	end repeat
	
	--------------------------------------------------------------------
	-- SET FOLDERS
	set myfolder to choose folder with prompt "IMAGE FILES?"
	set dstfolder to choose folder with prompt "DESTINATION FOLDER?"
	
	----------------------------------------------------------------------
	--START PROCESS
	tell application "Finder"
		
		set myfiles to every file of folder myfolder whose name does not start with "." and (file type is in {"TIFF", "JPEG"} or name extension is in {"tiff", "tif", "jpeg", "jpg"})
		
		repeat with i from 1 to number of items in myfiles
			
			set thename to (item i of myfiles as string)
			
			if thename is in mylist_1 then
				
				duplicate file named thename of myfolder to dstfolder
				
			end if
			
		end repeat
	end tell
end timeout

Try something like this, DE:


set aFile to choose file with prompt "Select a file to read:" without invisibles
set myfolder to choose folder with prompt "IMAGE FILES?"
set dstfolder to choose folder with prompt "DESTINATION FOLDER?"

tell application "Finder" to duplicate (myfolder's files whose (file type is in {"TIFF", "JPEG"} or name extension is in {"tiff", "tif", "jpeg", "jpg"}) and name is in (read aFile)'s paragraphs) to dstfolder


Thanks Kia! It does work…sort of. my text file list has 128 items and my folder with images has 1330 files. The script does work if I apply it to a list and folders with significantly fewer files. However, when i apply the script to my list and files it just quits quietly. I added a timeout, but it quits well before the limit. Any thoughts? is there a limitation in how many files the script can read from a folder?

thanks

does anyone know why there would be a limitation with hundreds of files? – see above post

Hi, DE;

You don’t tell us anything about your setup, your system, or how much memory you have so it’s a bit hard to say what might be happening. Run your script with a try block in it to capture whatever error has occurred:

set aFile to choose file with prompt "Select a file to read:" without invisibles
set myfolder to choose folder with prompt "IMAGE FILES?"
set dstfolder to choose folder with prompt "DESTINATION FOLDER?"
try
	tell application "Finder" to duplicate (myfolder's files whose (file type is in {"TIFF", "JPEG"} or name extension is in {"tiff", "tif", "jpeg", "jpg"}) and name is in (read aFile)'s paragraphs) to dstfolder
on error theError
	display dialog theError
end try

Sorry, Here’s the stats:
G4/1.67mhz powerbook
1.5 Gig SDRAM
OS 10.4.7

Here is the event log with a try block:

tell current application
choose file with prompt “Select a file to read:” without invisibles
alias “Macintosh HD:Users:DE:Desktop:textfile.txt”
choose folder with prompt “IMAGE FILES?”
alias “Macintosh HD:Users:DE:Desktop:PREVIEWS:FINALS:portrait:”
choose folder with prompt “DESTINATION FOLDER?”
alias “Macintosh HD:Users:DE:Desktop:PREVIEWS:FINALS:here:”
end tell
tell application “Finder”
read alias “Macintosh HD:Users:DE:Desktop:textfile.txt”
«event ascrgdut»
{}
read alias “Macintosh HD:Users:DE:Desktop:textfile.txt”
"

here’s the other part of the results:

read alias "Macintosh HD:Users:dwight:Desktop:Travel Landscape.txt"
	"

tell current application
choose file with prompt “Select a file to read:” without invisibles
alias “Macintosh HD:Users:dwight:Desktop:Travel Landscape.txt”
choose folder with prompt “IMAGE FILES?”
alias “Macintosh HD:Users:dwight:Desktop:PREVIEWS:FINALS:portrait:”
choose folder with prompt “DESTINATION FOLDER?”
alias “Macintosh HD:Users:dwight:Desktop:PREVIEWS:FINALS:here:”
end tell
tell application “Finder”
read alias “Macintosh HD:Users:dwight:Desktop:Travel Landscape.txt”
«event ascrgdut»
{}
read alias “Macintosh HD:Users:dwight:Desktop:Travel Landscape.txt”
"

kai’s script works for me with 206 items in the text file and about 1600 image files in the folder. In the Event Log, after the read alias line, I get the text from the file, followed, after a pause, by a list of Finder references to the duplicated files.

From your Event Log, it looks as though there’s something odd happening when the text file’s read. I’ve no idea what «event ascrgdut» is. The empty list could be the result of not duplicating any files. And then there’s another read. Very odd.

Is your text file plain text and in good health?

See: This by Jon Pugh

So one or two broad questions follow on from those results, DE:

Do you have any third-party scripting additions installed and, if so, what happens when you disable them (move them to another folder and quit/relaunch Script Editor)?

How are you creating the text file (using the ‘write’ command or a text editor ” and, if the latter, which one)? Are there any differences between how you produced the text file for the previous ‘short’ test run and that for the main one? (And can we safely assume that the internal attempt to access some aete resource ” the ascrgdut event ” is not logged during the short test?)

It might also be worth trying the to run the read command on the file in isolation, without any Finder tell statement ” just to check what happens there.

And if those don’t turn up a helpful clue, checking the health of your copy of Standard Additions might even be on the cards… :confused:

Thanks guys,

Nigel, My script does read the text file accurately. My list is not empty. It is during my posting that for some reason only part of my message acually makes it. You will notice I have made several attempts and it appears I’m posting the same thing over and over.

Kai, I have no third party scripting additions installed. I created the text file using this script:

set output_ to (choose file name with prompt “Choose a name and location for the new text file.”)

tell application “Finder”
set files_ to selection
set names_ to “”
repeat with file_ in files_
set names_ to names_ & ((name of file_) & return)
end repeat
end tell

if (count files_) is not 0 then
try
set file_ref to open for access output_ with write permission
write names_ to file_ref starting at eof
try
close access file_ref
end try
on error e
display dialog e
try
close access file_ref
end try
end try
end if

Hi, DE.

Text written to file with your script in Tiger will be Unicode text, not plain text, so you’ll need to read it back as such:

-- Change this .
tell application "Finder" to duplicate (myfolder's files whose (file type is in {"TIFF" ,"JPEG" } or name extension is in {"tiff" ,"tif" ,"jpeg" ,"jpg" }) and name is in (read aFile)'s paragraphs) to dstfolder 

-- . to this:
tell application "Finder" to duplicate (myfolder's files whose (file type is in {"TIFF" ,"JPEG" } or name extension is in {"tiff" ,"tif" ,"jpeg" ,"jpg" }) and name is in (read aFile as Unicode text)'s paragraphs) to dstfolder

That’s probably why you couldn’t post your Event Log. The two-bytes-per-character Unicode was being interpreted as one-byte-per-character text. The Unicode’s high-order bytes were thus rendered as individual, invisible, unprintable characters in the string.

A couple of points of geekery not directly linked to the problem:

  1. Since the files’ names and the names in the text already have extensions, there’s no need to check for name extensions separately. There’s probably no need to check for file types either. However, it doesn’t seem to affect performance times.

  2. Since at least Jaguar, the Finder has had a bug whereby it doesn’t differentiate between names like “file1.jpg” , “file01.jpg”, and “file001.jpg” when it’s performing bulk actions such as whose filters. Files with those names can be referenced individually, but a filter for any one of them by name will return all of them that exist in the target location.

I wrote a handler this morning to get round this and tried it with kai’s script to see how much longer if would take. Amazingly, it turns out to be significantly faster, even when there are no false matches to weed out! Duplicating 206 files filtered by name takes about 32 seconds with kai’s script on my G5. Adding in my name-checking handler, it only takes about 20.

on checkNumericNames(targetNames, FinderRef)
	tell application "Finder"
		try
			set potentialItems to FinderRef as alias list
		on error
			set potentialItems to {FinderRef as alias}
		end try
	end tell
	repeat with thisfile in potentialItems
		if (name of (info for thisfile) is in targetNames) then
		else
			set thisfile's contents to missing value
		end if
	end repeat
	
	return potentialItems's aliases
end checkNumericNames

set aFile to choose file with prompt "Select a file to read:" without «class lfiv»
set myfolder to choose folder with prompt "IMAGE FILES?"
set dstfolder to choose folder with prompt "DESTINATION FOLDER?"
set nameList to (read aFile)'s paragraphs -- or: set nameList to (read aFile as Unicode text)'s paragraphs

try
	tell application "Finder" to duplicate (my checkNumericNames(nameList, a reference to (myfolder's files whose name is in nameList))) to dstfolder
on error theError
	display dialog theError
end try

Nigel, info for by default passes the argument with size (at least on Tiger).
Using info for thisfile without size might make it run even faster, but probably not by much.

Thanks for the tip, Qwerty. I was only vaguely aware of info for’s new without size ability and hadn’t realised that it could be applied with files too. (It was introduced because getting the sizes of large or deep folders could take ages, which was annoying if you didn’t actually want that information.) It doesn’t seem to make the script reliably faster on my machine; but on a slower one, or with more files to test, it might begin to make a difference.

One thing I have noticed is that, since adapting kai’s script and my version of it to work with a Unicode text file instead of a plain text file, a further two-and-a-bit seconds have been knocked off both running times. The names of the files in the folder come off the disk as Unicode text, so comparing them with a list of Unicode texts rather than a list of strings saves a lot of background coercion ” two-and-a-bit seconds’ worth in my case! (206 names in the list, 1648 files in the folder, 2 GHz DP G5.) With a plain text file, the read result can be coerced to Unicode before its paragraphs are extracted, which is just as good for the overall speed:

-- With a Unicode text file.
set nameList to (read aFile as Unicode text)'s paragraphs

-- With a plain text file:
set nameList to ((read aFile) as Unicode text)'s paragraphs

Hey Guys I tried Nigel’s script. Here’s my event log. It doesn’t do anything in my environment. Ay thoughts?

Event Log:

tell current application
choose file with prompt “Select a file to read:” without invisibles
alias “Macintosh HD:Users:DE:Desktop:textdoc.txt”
choose folder with prompt “IMAGE FILES?”
alias “Macintosh HD:Users:DE:Desktop:PREVIEWS:FINALS:portrait:”
choose folder with prompt “DESTINATION FOLDER?”
alias “Macintosh HD:Users:DE:Desktop:PREVIEWS:FINALS:here:”
read alias “Macintosh HD:Users:DE:Desktop:textdoc.txt”
"

-- Change this .
set nameList to (read aFile)'s paragraphs

-- . to this:
set nameList to (read aFile as Unicode text)'s paragraphs

OK. This version cuts the process down to just under seven seconds on my machine! The actual duplication time is exactly the same, but as it’s AppleScript rather than the Finder that does the thinking, the thinking time is very much reduced.

The Finder reference passed to the handler now covers all the files in the source folder, regardless of name. The handler (now-renamed) gets a list of Unicode text paths to the items covered by the reference and only returns the ones that end with a name from the text file. The names from the text file are kept as a single text, as comparisons with this are faster than with a list of individual names. The Finder’s duplicate command is apparently happy to take a list of paths as its parameter, so there no need to convert these back to aliases or Finder items first.

on whoseNameIsIn(targetNames, FinderRef)
	set astid to AppleScript's text item delimiters
	
	set AppleScript's text item delimiters to return
	-- Ensure that the list of names is a single, return-delimited Unicode text with returns at each end.
	set targetNames to {"", get (targetNames as Unicode text)'s paragraphs, ""} as Unicode text
	-- Coerce the Finder reference to Unicode text, using delimiter return. Each paragraph of the result is a path.
	tell application "Finder" to set allPaths to (FinderRef as Unicode text)
	
	-- Lose any incidences of ":" at the ends of paths. (Folders, disks, packages, etc.)
	set AppleScript's text item delimiters to ":" & return
	set allPaths to allPaths's text items
	
	-- Separate the paths to the referenced items.
	set AppleScript's text item delimiters to return
	set allPaths to (allPaths as Unicode text)'s paragraphs
	
	script o -- For list referencing speed.
		property paths : allPaths
	end script
	
	-- Zap all paths with non-matching names.
	set AppleScript's text item delimiters to ":"
	repeat with i from 1 to (count allPaths)
		if (return & (text item -1 of item i of o's paths) & return is in targetNames) then
		else
			set item i of o's paths to missing value
		end if
	end repeat
	set AppleScript's text item delimiters to astid
	
	-- Return the surviving paths.
	return o's paths's every Unicode text
end whoseNameIsIn

set aFile to choose file with prompt "Select a file to read:" without «class lfiv»
set myfolder to choose folder with prompt "IMAGE FILES?"
set dstfolder to choose folder with prompt "DESTINATION FOLDER?"
set nameList to (read aFile as Unicode text) -- A Unicode text file is assumed here.

try
	tell application "Finder" to duplicate (my whoseNameIsIn(nameList, a reference to (myfolder's files))) to dstfolder
on error theError
	display dialog theError
end try

I dare say a shell script would be faster still. :wink: