Need help with Recursive File Comparison with Duplication

Hi, all I am new to Applescript and the support community. I am working on developing a script that takes a folder and replaces its original music content with aliases from an organized Library. Let me explain a little better… I have a list of project folders that all contain folders and original music. My company uses iTunes to store and organize their music. Once iTunes has imported the music and has made a copy of the original file and organizes it accordingly we create an alias within the iTunes Library and manually drag and drop the aliases into our Project folders. Once the files are organized into itunes I take this script that makes aliases without replacement of the original files in the folders. Ultimately we have to take the aliases(that is linked to the organized library) and drop them into project folders that already have the orginal files in them.

The objective is to save space and continue to let iTunes organize and copy files for us. I already have made a script that generates aliases into the subfolders of iTunes organized Library withour replacing the file that iTunes created. I also made a script that takes the itunes library and dumps all the aliases into a designated folder. I thought this may be helpful for drawing aliases to files that are in our project folder but seem to be stuck.

here is the code work for the first step in this process (this script is a droplet) that takes all files and subfolder files and makes aliases directing them to a (choose) source folder":


--code starts here--

property theTotalCount : 0
property FolderName : ""
on open these_items
	set FolderName to (choose folder with prompt "Please choose the directory to store your aliases:")
	set theTotalCount to 0
	repeat with i from 1 to the count of these_items
		set this_item to (item i of these_items)
		set the item_info to info for this_item
		if folder of the item_info is true then
			process_folder(this_item)
		else if (alias of the item_info is false) then
			my process_item(this_item)
		end if
	end repeat
	tell application "Finder"
		activate
		with timeout of 9999 seconds
			display dialog "Total Aliases Created: " & theTotalCount buttons "OK" default button "OK" with icon 2 giving up after 9990
		end timeout
	end tell
end open
on process_folder(this_folder)
	set these_items to list folder this_folder without invisibles
	repeat with i from 1 to the count of these_items
		set this_item to alias ((this_folder as text) & (item i of these_items))
		set the item_info to info for this_item
		if folder of the item_info is true then
			process_folder(this_item)
		else if (alias of the item_info is false) then
			my process_item(this_item)
		end if
	end repeat
end process_folder
on process_item(this_item)
	tell application "Finder" to make new alias file at FolderName to this_item
	set theTotalCount to theTotalCount + 1
end process_item

 --end code

this script is working fine. so we now have dropped our iTunes Library music files into our script and it created aliases of all the iTunes Library and directed them into a folder named Aliases.

Second Step is dropping a Project folder with original files and subfolders with original files in them that have different path names than the copies that iTunes automatically makes when organizing. When you drop a project folder into this droplet it prompts you to scan an alias folder to compare contents and match the alias files with the music files in the project folders.


--code begins

property theTotalCount : 0
property FolderName : ""
property alias_files : {}
on open these_items
	set FolderName to (choose folder with prompt "Please choose the directory of aliases to scan:")
	tell application "Finder"
		activate
		with timeout of 99999 seconds
			set alias_files to every file of folder FolderName whose kind is "Alias"
		end timeout
	end tell
	set theTotalCount to 0
	repeat with i from 1 to the count of these_items
		set this_item to (item i of these_items)
		set the item_info to info for this_item
		if folder of the item_info is true then
			process_folder(this_item)
		else if (alias of the item_info is false) then
			my process_item(this_item, alias_files)
		end if
	end repeat
	tell application "Finder"
		activate
		with timeout of 99999 seconds
			display dialog "Matched Files: " & theTotalCount buttons "OK" default button "OK" with icon 2 giving up after 99990
		end timeout
	end tell
end open

on process_folder(this_folder)
	set these_items to list folder this_folder without invisibles
	repeat with i from 1 to the count of these_items
		set this_item to alias ((this_folder as text) & (item i of these_items))
		set the item_info to info for this_item
		if folder of the item_info is true then
			process_folder(this_item)
		else if (alias of the item_info is false) then
			my process_item(this_item, alias_files)
		end if
	end repeat
end process_folder

on process_item(this_item, alias_files)
	tell application "Finder"
		repeat with this_alias in alias_files
			if this_item's name is equal to (original item of this_alias)'s name then
				duplicate this_alias to this_item's container
				set theTotalCount to theTotalCount + 1
				exit repeat
			end if
		end repeat
	end tell
end process_item

--end code

The Second script works on small folders with small alias source folders to match with files, but on source folders with ex: 500 songs it times out. I’ve tried several versions
the objective is to place a Newly copied and organized library songs with alias files (that are directed to the itunes folder) into the existing projects folders that are currently being used…
Any suggestions would be greatly appreciated.

But before you do that, you want to see if there is a root-folder with the same name, and if there is aliases in there, that isn’t in the original folder/subfolder, then you want to remove those aliases, before you replace the entire contents, with the new contents of your Itunes folder?

Not quite. I don’t want to remove any aliases. I’m taking iTunes generated library, dropping the entire Library into my first script, and letting the first script make aliases of the all the songs in itunes library. After all the aliases of the itunes music is stored in a folder ex"alias folder". The second script you will take a project folder ex"the hangover" that has music files in its folder and subfolders. The second script compares item info and duplicates an alias from “alias folder” into the project folder/subfolders.

sorry its a bit confusing. The second script works but only when working with small quantities of alias files to match. if you have a large number of aliases in your “aliases folder” it times out.

Maybe your code fires away so many events, that you congest the whole eventqueue?

A possible solution, could be to insert some small delays here and there, lets say of 0.2 seconds per file for starters,
and then increase the delay, until everything goes through?

Another possible improvement, is to try closing all finder windows, and see if that helps, If it does, then maybe swapping Finder for SystemEvents may help you.

Just an idea. I really whishe’d there was a way to create an alias, that didn’t involve AppleEvents, but I don’t think there is. But maybe a symbolic link can provide the desired result? Please check man ln in a terminal window.

The advantage of using symlinks, would be that you didn’t have to do anything involving AppleEvents, to mirror the structure, but solve the problem with some good old bash shell-scripting. :slight_smile:

Hello.

You are a bit in luck, as I have learned that you can create aliases with a do shell script command, using the SetFile utility. Try searching for SetFile on this page.

The do shell script command doesn’t use events.But you need to have DeveloperTools/Xcode installed, and as it stands in the Article, you’ll probably have to restart Finder when you are done.

I’m still trying to understand what’s happening, but can’t you use a ‘with timeout’ block?

Hi,

retrieving the name of the files in each iteration again and again is very expensive and not effective.
Retrieve the file names instead of the file references once and check the existence in the list.

Try this, as the list of alias files is defined as property, it’s not necessary to pass it as handler parameter


property theTotalCount : 0
property FolderReference : ""
property alias_fileNames : {}

on open these_items
	set FolderReference to (choose folder with prompt "Please choose the directory of aliases to scan:")
	tell application "Finder"
		activate
		with timeout of 99999 seconds
			set alias_fileNames to name of every file of FolderReference whose kind is "Alias"
		end timeout
	end tell
	set theTotalCount to 0
	repeat with i from 1 to the count of these_items
		set this_item to (item i of these_items)
		set the item_info to info for this_item
		if folder of the item_info is true then
			process_folder(this_item)
		else if (alias of the item_info is false) then
			my process_item(this_item)
		end if
	end repeat
	tell application "Finder"
		activate
		with timeout of 99999 seconds
			display dialog "Matched Files: " & theTotalCount buttons "OK" default button "OK" with icon 2 giving up after 99990
		end timeout
	end tell
end open

on process_folder(this_folder)
	set these_items to list folder this_folder without invisibles
	repeat with i from 1 to the count of these_items
		set this_item to alias ((this_folder as text) & (item i of these_items))
		set the item_info to info for this_item
		if folder of the item_info is true then
			process_folder(this_item)
		else if (alias of the item_info is false) then
			my process_item(this_item)
		end if
	end repeat
end process_folder

on process_item(this_item)
	tell application "Finder"
		set thisItemsName to this_item's name
		if thisItemsName is in alias_fileNames then
			duplicate alias file thisItemsName of FolderReference to this_item's container
			set theTotalCount to theTotalCount + 1
		end if
	end tell
end process_item


PS: Here’s another example to save Apple Events>
Retrieving name and container reference sends only one event


on process_item(this_item)
	tell application "Finder"
		set {container:thisItemsContainer, name:thisItemsName} to this_item
		if thisItemsName is in alias_fileNames then
			duplicate alias file thisItemsName of FolderReference to thisItemsContainer
			set theTotalCount to theTotalCount + 1
		end if
	end tell
end process_item


Thanks I’ll try this today and see how it works. I appreciate all of the information and will report back with results.

Thanks that’s some good info. My friend and I have written a shell script to do this process but I was hoping to do everything in applescript. I will look into all these options today and report back with my results.

I tried StefanK’s edited version of my second script and it stopped responding. I tried adding delays but that didn’t work either. :expressionless: I am still tinkering with the script trying to figure out where its getting to when it crashes.