Alias script concept

Thank you @KniazidisR ,

That’s a pretty neat approach to things. It includes so much script stuff that I’ve never seen before, you’re AppleScript skills are certainly apparent compared to my lack of knowledge. :—)

I tried your script on a mirrored disk to test it. Since I didn’t fully know what it would be doing with things. Given my alias situation here is what my test resulted in.

• It spent a lot of time “Running …” of course initially but also in between queries.
• The prompt comes up with multiple aliases, but only trashes one alias and seemingly not all related aliases
• After it did numerous using the script. While it was running, I checked the trash and manually searched, it appears to not be finding or replacing all relative aliases
• The prompt also includes other file types at times like .html etc.,
• I eventually got a “Script Error: Apple event timed out” maybe due to me not reacting to the prompt in time or something?

It’s an impressive approach for sure. Although given my situation even though it tries to be a more automated approach it seems maybe to take longer than my proposed approach due to the “Running …” between queries of found instances. Also it seems to not be finding and replacing all relative alias instances. If you think you can and want to improve your proposed approach that’s certainly welcome.

But regardless if it’s not too much to ask can you please help me fix my initial approach also? I think the manual search is going to be more effective and fail safe in allowing me to work from a manual selection. Allowing me to accurately ensure that all instances of aliases get resolved to the original folder as described in my initial post. I would really like to have a working version of this approach available, even if a more automated approach can accurately be accomplished.

I greatly appreciate your time and willingness to help me. You have certainly opened my eyes to things and approaches I never really knew existed for my possible future discovery. I really welcome your or anybodies help in correcting my more manual described and shown approach in my initial post. If you would be so kind and generous to help me with it, I would be very grateful to have that approach.

Thank you so much.

I have added in post #5 instructions for increasing the timeout so that timeout errors should no longer occur.

Now, for the rest - don’t test the speed of the script on an external drive, as the script tries to take advantage of Spotlight’s speed.

There will always be much less broken aliases than file system elements. For example, in my domain I found only 1 broken alias and about 300,000 elements. I will fix this 1 broken alias, not the aliases of 300,000 items.

I will not write a script following the reverse logic of things. Because first there is 1 broken file alias, and then it (and only it) is corrected if you find 1 (and only one) corresponding original. Then - processing of the next broken alias, one at a time. And not like yours - on the contrary - you are looking for alias files for each element, of which there may be many, and some may be quite working.

Also, the script cannot be “instant”, since every time there is a search in the folder and subfolders. This is logical and to be expected.

My test only had a singular internal SSD disk which is already indexed with Spotlight inside a cMP. So that is not an issue regarding external drive, etc. Though the search portion of the script seemed slower than searching manually with a given criteria and getting accurate returns then a finder search? Of course it’s then certainly faster (than manual clicks) after that when relinking / recreating the aliases but it didn’t accurately target all the associated instances or recreate them.

As mentioned previously I already know which are broken and which are not. So even with a manual search and selection I would only be targeting the broken aliases for replacement.

The only aliases I want to replace (obviously broken) are the ones I already know are associated with an original. I just want to manually target multiple aliases and also point to a corresponding folder via a selection.Then automate the portion of the relinking / remaking process of each alias at its current location and delete the broken one. That’s all I want from the Manual approach, search, make selection (folder + aliases) - Then Automated delete broken, recreate selected aliases associated to the selected folder at their current location. Rinse & repeat.

Are you saying with your script if there are 20 aliases of a folder then I have to pick the same folder eventually in the prompt 20 times to recreate them as they are found? I guess I don’t fully understand what you are saying otherwise? In my test your script is not finding all the associated aliases of the folder so maybe that is what you mean by “one at a time”.

If so then I really believe working from a manual selection would be more accurate and proficient in my case. To do a singular search and then replace them all at once, repeat. I just can’t figure out how to get that working fully. So I signed up and I’m asking here.

Please understand that anything I say or express is certainly not against your script or abilities. Maybe the situation I have is just more complex than what can be fully automated accurately or in an efficient manner. But I think it could be accomplished if I could get my described partially manual and partially automated approach working.

Thank you

Well, since you insist, then try this script, which I wrote based on yours:


tell application "Finder"
	set selItems to selection
	
	repeat with curItem in selItems
		if kind of curItem is "Folder" then
			set originalItem to folder (contents of curItem as text)
			exit repeat
		end if
	end repeat
	
	repeat with currentFile in selItems
		if kind of currentFile is "Alias" then
			set theContainer to container of currentFile
			delete currentFile
			try
				make alias file at theContainer to originalItem
			end try
		end if
	end repeat
end tell

Thanks so much @KniazidisR. Can you please modify it so it keeps the same name of the original alias for the recreated alias thats being made. That would be the only remaining thing I had hoped to accomplish.

I’m not sure if the below is what does that from your initial automated version? I can’t seem to understand how that’s being used in your script.

set brokenAliasFileName to text 1 thru -7 of (get name of file ((contents of brokenAliasFile) as text))

Also for understanding, reverting back to my original post. Is it correct to assume “set original item” does not work on broken aliases and they must instead be recreated?

Thanks so much for your assistance, time and knowledge KniazidisR, it’s greatly appreciated.

It is easy:


tell application "Finder"
	set selItems to selection
	
	repeat with curItem in selItems
		if kind of curItem is "Folder" then
			set originalItem to folder (contents of curItem as text)
			exit repeat
		end if
	end repeat
	
	repeat with currentFile in selItems
		if kind of currentFile is "Alias" then
			set theContainer to container of currentFile
			set oldName to name of currentFile
			delete currentFile
			try
				set newAlias to make alias file at theContainer to originalItem
				set name of newAlias to oldName
			end try
		end if
	end repeat
end tell

Yes.

This is how my other script defines itself search term. Every alias file ends with " alias", so script cuts this word and remains only base name of alias file, which is used as search term further. Search term is used in the shell’s find command as you can see. It finds every file and every folder (in the subfolders of home folder too), whose name begins with search term. The ending is wirdcard (*) as you see. It can be any. (“.mp3”, “.pdf”, “bla_bla.pdf”, “Untitled folder”)

Easy for you KniazidisR, thats for sure. :smiley:

Now that I see my concept fixed by you and working that simple code actually is starting to make sense to me. Also thanks for the feedback on “set original item” regarding broken aliases, its a pitty thats not an option also.

I may never (or at least for a long time) understand your more automated approach :—). But now having these two approaches provided so graciously by you, it should really help me to more easily correct these broken aliases faster and with less direct intervention. I really appreciate you sharing your automated approach that’s indeed wonderful also.

I’m super thankful for your input and getting things working for me. That’s awesome.

Side note: This is how I originally gathered the broken aliases list, it was manual (though not too bad) and you will probably laugh. :–D

• Finder search for ‘alias’ and save the search
• Then from that save folder ‘get info’ in batches of 140 aliases down the results in the folder
• Once all the ‘get info’ windows open in a brief moment the finder resolves all aliases that it can
• Close all windows Option-Command-W
• Re-open saved search and repeat from where last left off with another 140, until all done
• Once done, scroll down past all the modified that the finder fixed and any that were not broken
• Multiple select and copy all that are remaining - aka broken
• Paste that list in text editor, sort, remove duplicates
• That’s the list of broken alias search terms to find (per the last script)

Crazy huh, but accurate. :stuck_out_tongue:

But after seeing your initial script above, I’m assuming a script could have produced the same list but all automated. It must be wonderful to have the ability to command AppleScript at your demand for whatever results you require.

I suppose a person could even script something that uses a generated ‘list’ of search terms (regardless of how generated) as an array. Then from this array does a finder search using ‘name matches’ for each item in the array. Then allows the user to make the custom selection. Then processes the aliases like your last script (folder + aliases) and repeats the prompts and process through the array until completion. That would prevent copying and pasting from the list and doing the search manually. But still allow the apporach of targeting multiples to be resolved at once like the last script.

It’s probably amazing what all can be scripted at will and accessed in the macOS and apps. This forum is inspiring and your help with this has been wonderful KniazidisR.

Can I download your brain from somewhere? ;–)

Here is a little bit of a different approach which you may find useful. It becomes especially handy if you want to address all of the “broken” alias files in a chosen folder or on your entire system, rather than only acting on currently selected items in Finder.

Any new created alias files in Finder will be named like this for example “Some File.txt alias” (with “alias” added to the name after the file extension). However, that alias file can be renamed and by removing the word “alias” from the name, it will still be recognized as an alias file.

This is where mdfind becomes extremely useful. Not only is mdfind Lightning Fast, it also will find the alias files that don’t have “alias” in the file name.

Before testing my full AppleScript code, I would suggest testing mdfind in Terminal.app and make sure it returns the results you’re looking for. For example, I used… [format]mdfind “kMDItemKind == ‘Alias’” | egrep -iv ‘ColorSync|adobe|paral|icloud|onyx’ | sort[/format]This returned the results to all alias files which do not have “ColorSync” or “adobe” or “paral” or “icloud” or “onyx” in its path name. (The -iv options for egrep mean… -i = case insensitive and -v = opposite of)

Then adjust the “do shell script” commands in the AppleScript code, as needed.

property originalFilesOfProperlyLinkedAliases : {}
property brokenAliasFiles : {}
property brokenAliasFilesNames : {}

-----------------------------------------------------------------------							
(* OPTION 1: Use This To Search The Entire Computer For Alias Files *)
--set aliasFiles to paragraphs of (do shell script "mdfind " & quoted form of "kMDItemKind == '*Alias*'")
-----------------------------------------------------------------------							
(* OPTION 2: Use This To Choose Folder To Search Through For Alias Files *)
set mdfindSearchOnlyInFolder to quoted form of POSIX path of (choose folder with prompt ¬
	"mdfind Only In Folder" with invisibles without multiple selections allowed)
set aliasFiles to paragraphs of (do shell script "mdfind -onlyin " & mdfindSearchOnlyInFolder & ¬
	" " & quoted form of "kMDItemKind == '*Alias*'")
-----------------------------------------------------------------------							

tell application "Finder"
	repeat with i from 1 to count of my aliasFiles
		set thisItem to item i of my aliasFiles as POSIX file as alias
		tell alias file thisItem
			try
				-- Who Knows, You May Need This List In The Future For Some Reason
				set end of my originalFilesOfProperlyLinkedAliases to original item as alias
			on error errMsg number errNum -- If original item Can't Be Found
				try
					set theContainer to thisItem's container
					set brokenAliasFileName to thisItem's name
					set end of my brokenAliasFiles to thisItem
					set end of my brokenAliasFilesNames to brokenAliasFileName
					
					if file type of thisItem is not "fdrp" then -- If Item Is Not A Folder
						set deletedAliasFile to delete thisItem -- Deletes Alias File If Link Is Broken
						try
							-----------------------------------------------------------------------							
							(* OPTION 1: Choose New Source File & Creates A New Alias
							 File With Name Of New Chosen Source File *)
							--set newAlias to (make new alias file at theContainer to ¬
							--	(choose file with prompt "Choose A New Source File For " & ¬
							--		brokenAliasFileName))
							-----------------------------------------------------------------------							
							(* OPTION 2: Choose New Source File & Creates A New Alias File 
								With Name Of The Original Deleted Alias File *)
							if "alias" is not in brokenAliasFileName then ¬
								set brokenAliasFileName to brokenAliasFileName & " alias"
							set name of (make new alias file at theContainer to ¬
								(choose file with prompt "Choose A New Source File For " & ¬
									brokenAliasFileName)) to brokenAliasFileName
							-----------------------------------------------------------------------							
						on error errMsg number errNum
							move deletedAliasFile to theContainer -- Undeletes Alias File If User Chooses Cancel
						end try
					else -- If Item Is A Folder
						set deletedAliasFile to delete thisItem
						try
							-----------------------------------------------------------------------							
							(* OPTION 1: Choose New Source Folder & Creates A New Alias File 
								With Name Of The New Chosen Source Folder *)
							--set newAlias to (make new alias file at theContainer to ¬
							--	(choose folder with prompt "Choose A New Source Folder For " & ¬
							--		brokenAliasFileName))
							-----------------------------------------------------------------------
							(* OPTION 2: Choose New Source Folder & Creates A New Alias File 
										With Name Of The Original Deleted Alias File *)
							if "alias" is not in brokenAliasFileName then ¬
								set brokenAliasFileName to brokenAliasFileName & " alias"
							set name of (make new alias file at theContainer to ¬
								(choose folder with prompt "Choose A New Source Folder For " & ¬
									brokenAliasFileName)) to brokenAliasFileName
							-----------------------------------------------------------------------
						on error errMsg number errNum
							move deletedAliasFile to theContainer -- Undeletes Alias File If User Chooses Cancel
						end try
					end if
				end try
			end try
		end tell
	end repeat
end tell

Thank you so much for your input and script also @wch1zpink. This thread is really becoming a wealth of information on the topic and demonstrating how to use various approaches. So that has truly been great.

Yep, I actually used mdfind as my initial step to evaluate the overall alias situation once I was experiencing various broken instances. It is indeed virtually instantaneous returning the results, I just used — mdfind kMDItemKind=“Alias”

What you have demonstrated using that method as an alternative is again very interesting. Though much of your script remains above my current comprehension :—). But throughout this thread there are really lots things that are helping to make sense in certain areas for me. So I’m very thankful for your input and script as well, thank you.

I really appreciate everyones input on this topic, it has been wonderful.

I just discovered the script that wch1zpink provided here on 5/15/21. It’s very nearly what I have wanted for many years!! First try, I found it more useful that any script or app that I have tried previously for repairing broken aliases.

With two modifications, it would be perfect. Hopefully, some scripting guru on this forum will be inclined to implement them:

First, when the “Choose a New Source File” menu comes up, I (i) double click on the original alias file name showing at the top, (ii) copy-paste that name into the nearby Spotlight search field, return, (iii) adjust the search range to “This Mac” usually, then (iv) select the correct original file from the search results. Because the files I am fixing have pretty unique names, this process almost always yields unambiguous results right away.

But, it would be even better if steps (i), (ii), and maybe (iii) were built into the script. Seems like that should be possible. Please?

Second, it appears that the script trashes the broken alias first, then creates a new one. So, if a new corrected alias isn’t created for any reason, there’s no reminder left in the original source folder. The original broken alias can be recovered from the trash (or TimeMachine), but that takes time. Furthermore, when the script is processing multiple aliases from a folder, there seems to be no way to interrupt it and leave the unprocessed aliases unchanged.

Not sure how to get around this issue, but at least a way to exit the script leaving unprocessed aliases unchanged would help. Thanks.

This is a new implementation based, loosely, on @wch1zpink 's concept. Feedback is always appreciated.

This script:

  1. Uses mdfind to locate all aliases in the selected folder whose original file is not available.
  2. Offers all available ( using mdfind again but from all available locations.) name-and-extension-matching files as potential new originals for the alias.
  3. Once a new original file has been selected it will re-link ( not re-make ) the broken Alias to the selected original file.
  4. Offers an option “Don’t re-link this alias.” you can use for aliases where an appropriate original file cannot be found.
  5. If no name-and-extension-matching potential originals are found the script skips the broken alias.
  6. You can cancel at any time to abandon un-corrected broken aliases.

Multiple required handlers are included from my local libraries. The three “Filesystem_Alias_…” handlers are new code and not robustly tested.

Note: this code will not flag an alias as broken if it’s original file is still in the Trash.

--9/8/25 https://www.macscripter.net/u/paulskinner/
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set fileSystemObject to quoted form of POSIX path of (choose folder with prompt "Select a folder to search for broken Aliases.")
set brokenAliasList to Filesystem_Alias_List_Broken(fileSystemObject)
repeat with thisBrokenAlias in brokenAliasList
	set thisBrokenAliasName to FileSystem_Object_Name_And_Extension(thisBrokenAlias)
	set thisBrokenAliasContainer to FileSystem_Object_Container(thisBrokenAlias)
	set potentialOriginalFiles to Filesystem_Alias_List_Potential_Originals(thisBrokenAliasName)
	if potentialOriginalFiles is not {} then Filesystem_Alias_Choose_New_Original_File(thisBrokenAlias, thisBrokenAliasContainer, thisBrokenAliasName, potentialOriginalFiles)
end repeat
display dialog "Alias re-linker complete."



EDIT

Crucial handlers removed until I can confirm this code will not misidentify broken aliases. For safety.

/EDIT







1 Like

This sounds terrific, but I haven’t been able to get it to work yet. The script seems to run, and returns “Alias re-linker complete.”, but there’s no change in the aliases in the selected folder. I tested several variations, but haven’t had time to investigate thoroughly.

BTW, I’m surprised this script somehow will “re-link (not re-make ) the broken alias”. Feedback during my prior efforts to crack this problem has always been that Apples’s alias files are proprietary, complex, subject to change without notice, etc. It seemed the only way around this would be to use the finder to replace the old ones with a new one.

Here I’m using ASObjC to “make” the alias. If it already exists in that location this code “updates” the target. I was surprised by this behavior as well.

As for the failure, does the script present any choose-from-list dialog at all? If not then it is likely not finding any potential new original files of the same name as the alias. If you have Script Debugger I would suggest that you step through and see the results of the steps in the loop. That should give you a clear idea of the problem.

Or you can replace the top-level code with the following to see what broken aliases and originals the script is finding.

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set fileSystemObject to quoted form of POSIX path of (choose folder with prompt "Select a folder to search for broken Aliases.")
set brokenAliasList to Filesystem_Alias_List_Broken(fileSystemObject)
display dialog "Found " & length of brokenAliasList & " broken alias files."
repeat with thisBrokenAlias in brokenAliasList
	set thisBrokenAliasName to FileSystem_Object_Name_And_Extension(thisBrokenAlias)
	set thisBrokenAliasContainer to FileSystem_Object_Container(thisBrokenAlias)
	set potentialOriginalFiles to Filesystem_Alias_List_Potential_Originals(thisBrokenAliasName)
	display dialog "Found " & length of potentialOriginalFiles & " possible original files."
	if potentialOriginalFiles is not {} then Filesystem_Alias_Choose_New_Original_File(thisBrokenAlias, thisBrokenAliasContainer, thisBrokenAliasName, potentialOriginalFiles)
end repeat
display dialog "Alias re-linker complete."

Hum, both scripts do present the initial dialog to choose a folder containing broken aliases.
Now, the modified script returns “Found 0 broken alias files”. (Didn’t try the debugger yet.)
But, running the older script by wch1zpink on the same folder does find broken aliases.

I am assuming that you have confirmed the files in question are actually broken aliases.

I am seeing incorrect results from the mdfind command. Investigating.

EDIT

The code…

do shell script "mdfind -onlyin 'posix path of target folder/' kMDItemKind == \"Alias\""

Is returning non-alias file results here. I’m now filtering the results to confirm they are aliases before listing them. The code does appear to return all aliases in the target folder, but it is ALSO returning non-alias results. This may be a problem with my spotlight index. I don’t know.

What happens if you use kMDItemContentType?

eg

kMDItemContentType == “com.apple.alias-file”

This matches the type identifier in applescript.

Mockman,

Thank you! kMDItemContentType returns all aliases and only aliases in my testing!

This version is a bit more polished with feedback on the located broken aliases and a report on the actions taken at the end. It correctly identifies all broken aliases on my boot drive in ~1 second and offers options to re-link, skip or delete broken aliases that it finds.

Hopefully this version works properly for others as well.

--9/8/25 https://www.macscripter.net/u/paulskinner/
--Running under AppleScript 2.8, MacOS 15.5
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
property deletedBrokenAliases : 0
property skippedBrokenAliases : 0
property repairedBrokenAliases : 0

set fileSystemObject to quoted form of POSIX path of (choose folder with prompt "Select a folder to search for broken Aliases.")
set brokenAliasList to Filesystem_Alias_List_Broken(fileSystemObject)
set foundNoticeString to "Found " & length of brokenAliasList & " broken alias files."
if length of brokenAliasList < 20 then
	copy brokenAliasList to brokenAliasNameList
	FileSystem_Objects_Names(brokenAliasNameList)
	set brokenAliasListText to String_Convert_List_To_String(brokenAliasNameList, return)
	set foundNoticeString to foundNoticeString & return & return & brokenAliasListText
end if
display dialog foundNoticeString with title "Located broken aliases"
repeat with thisBrokenAlias in brokenAliasList
	set thisBrokenAliasName to FileSystem_Object_Name_And_Extension(thisBrokenAlias)
	set thisBrokenAliasContainer to FileSystem_Object_Container(thisBrokenAlias)
	set potentialOriginalFiles to Filesystem_Alias_List_Potential_Originals(thisBrokenAliasName)
	if potentialOriginalFiles is not {} then
		set userCancelled to Filesystem_Alias_Choose_New_Original_File(thisBrokenAlias, thisBrokenAliasContainer, thisBrokenAliasName, potentialOriginalFiles)
		if userCancelled then
			display dialog "User cancelled."
			exit repeat
		end if
	else
		set skippedBrokenAliases to skippedBrokenAliases + 1
	end if
end repeat
set conclusionText to "Alias re-linker complete." & return
set conclusionText to conclusionText & return & repairedBrokenAliases & " broken aliases were re-linked to a valid original file." & return
set conclusionText to conclusionText & return & skippedBrokenAliases & " broken aliases were skipped. Either no original files with the same name were found or the user did not select a new original file." & return
set conclusionText to conclusionText & return & deletedBrokenAliases & " broken aliases were deleted." & return
display dialog conclusionText








on Filesystem_Alias_Choose_New_Original_File(thisBrokenAlias, thisBrokenAliasContainer, thisBrokenAliasName, potentialOriginalFiles)
	set canceledState to false
	set potentialOriginalFiles to potentialOriginalFiles & "Don't re-link this alias."
	set potentialOriginalFiles to potentialOriginalFiles & "Delete this alias."
	try
		set chosenAlias to choose from list potentialOriginalFiles with prompt "The listed files have the same name as the broken alias '" & thisBrokenAliasName & "'" & return & return & "Choose a new original file for this alias:" & return & return & thisBrokenAlias & return with title "Choose new original file" default items "Don't re-link this alias."
		if chosenAlias is false then
			set skippedBrokenAliases to skippedBrokenAliases + 1
			return true
		end if
		if chosenAlias is not {} and chosenAlias is not in {"Don't re-link this alias.", "Delete this alias."} then
			set newAlias to FileSystem_Object_Alias_Make(item 1 of chosenAlias, thisBrokenAliasContainer, thisBrokenAliasName)
			set repairedBrokenAliases to repairedBrokenAliases + 1
		else
			if chosenAlias is {"Delete this alias."} then
				FileSystem_Object_Delete(thisBrokenAlias)
				set deletedBrokenAliases to deletedBrokenAliases + 1
			end if
		end if
	end try
	return canceledState
end Filesystem_Alias_Choose_New_Original_File
on Filesystem_Alias_List_Broken(fileSystemObject)
	set ss to "mdfind -onlyin " & fileSystemObject & " " & "kMDItemContentType == \"com.apple.alias-file\""
	set aliasFileList to paragraphs of (do shell script ss)
	set brokenAliasList to {}
	repeat with thisAliasFile in aliasFileList
		set thisAliasFile to contents of thisAliasFile
		try
			FileSystem_Object_Alias_Resolve(thisAliasFile)
		on error e number n
			{e, n}
			if n is -1700 then set the end of brokenAliasList to thisAliasFile
		end try
	end repeat
	return brokenAliasList
end Filesystem_Alias_List_Broken
on Filesystem_Alias_List_Potential_Originals(thisBrokenAliasName)
	--Find potential originalFiles
	thisBrokenAliasName
	set thisBrokenAliasSEARCHName to item 1 of String_Text_Items_Of(thisBrokenAliasName, {" alias"})
	
	set searchShellScript to "mdfind -literal 'kMDItemFSName == \"" & thisBrokenAliasSEARCHName & "\"'"
	set potentialOriginalFiles to paragraphs of (do shell script searchShellScript)
	set finalPotentialAliasOriginalFiles to {}
	repeat with thisPotentialAliasOriginal in potentialOriginalFiles
		set thisPotentialAliasOriginal to contents of thisPotentialAliasOriginal
		set thisPotentialAliasOriginalReference to FileSystem_Convert_Object_To_Alias(thisPotentialAliasOriginal)
		tell application "System Events"
			set thisPotentialAliasOriginalKind to kind of thisPotentialAliasOriginalReference
			if thisPotentialAliasOriginalKind is not in {"Alias"} then
				set the end of finalPotentialAliasOriginalFiles to thisPotentialAliasOriginal
			end if
		end tell
	end repeat
	return finalPotentialAliasOriginalFiles
end Filesystem_Alias_List_Potential_Originals

on FileSystem_Convert_Object_To_Alias(fileSystemObject)
	try
		if class of fileSystemObject is text then --check for a quoted posix path and remove the quoting
			if character 1 of fileSystemObject is "'" and character -1 of fileSystemObject is "'" then set fileSystemObject to text 2 thru -2 of fileSystemObject
		end if
		try
			return fileSystemObject as alias
		on error
			try
				return (POSIX path of fileSystemObject) as alias --handles Posix files
			on error
				return (POSIX file (fileSystemObject as text)) as alias --handles Posix paths
			end try
		end try
	on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
		error "<FileSystem_Convert_Object_To_Alias>" & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
	end try
end FileSystem_Convert_Object_To_Alias
on FileSystem_Convert_Objects_To_Aliases(fileSystemObjectList)
	try
		set fileSystemObjectList to (fileSystemObjectList) as list
		repeat with currentIndex from 1 to length of fileSystemObjectList
			set item currentIndex of fileSystemObjectList to FileSystem_Convert_Object_To_Alias(item currentIndex of fileSystemObjectList)
		end repeat
		return fileSystemObjectList
	on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
		error "<FileSystem_Convert_Objects_To_Aliases>" & space & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
	end try
end FileSystem_Convert_Objects_To_Aliases
on FileSystem_Convert_Object_To_NSURL(fileSystemObject)
	try
		set fileSystemObject to FileSystem_Convert_Object_To_PosixPath(fileSystemObject)
		set fileSystemObject to current application's class "NSURL"'s fileURLWithPath:fileSystemObject
		return fileSystemObject
	on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
		error "<FileSystem_Convert_Object_To_NSURL>" & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
	end try
end FileSystem_Convert_Object_To_NSURL
on FileSystem_Convert_Object_To_PosixPath(fileSystemObject)
	try
		try
			set posixPath to POSIX path of fileSystemObject
		on error
			try
				tell application "System Events"
					set posixPath to POSIX path of ((path of disk item (fileSystemObject as string)) as alias)
				end tell
			on error
				set posixPath to POSIX path of (fileSystemObject as alias)
			end try
		end try
		return current application's NSString's stringWithString:posixPath
	on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
		error "<FileSystem_Convert_Object_To_PosixPath>" & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
	end try
end FileSystem_Convert_Object_To_PosixPath

on FileSystem_Object_Alias_Make(fileSystemObject, aliasDestinationFolder, thisAliasName)
	-- Creates an alias file at the provided path
	set originalURL to FileSystem_Convert_Object_To_NSURL(fileSystemObject)
	set originalName to FileSystem_Object_Name_And_Extension(fileSystemObject)
	set targetFolder to FileSystem_Convert_Object_To_NSURL(aliasDestinationFolder)
	set theAliasPath to (targetFolder as text) & thisAliasName
	set theAliasURL to FileSystem_Convert_Object_To_NSURL(theAliasPath)
	set {theData, theError} to originalURL's bookmarkDataWithOptions:1024 includingResourceValuesForKeys:(missing value) relativeToURL:(missing value) |error|:(reference) -- 1024 = NSURLBookmarkCreationSuitableForBookmarkFile
	if theData is missing value then error (theError's |localizedDescription|() as text) number (theError's code() as integer)
	set {theResult, theError} to current application's |NSURL|'s writeBookmarkData:theData toURL:theAliasURL options:0 |error|:(reference)
	if not (theResult as boolean) then error (theError's |localizedDescription|() as text) number (theError's code() as integer)
	return theAliasURL
end FileSystem_Object_Alias_Make
on FileSystem_Object_Alias_Resolve(fileSystemObject)
	set theAliasURL to FileSystem_Convert_Object_To_NSURL(fileSystemObject)
	set the AliasURLString to (theAliasURL) as text
	set {theData, theError} to current application's |NSURL|'s bookmarkDataWithContentsOfURL:theAliasURL |error|:(reference)
	if theData is missing value then error (theError's |localizedDescription|() as text) number (theError's code() as integer)
	set theDict to current application's |NSURL|'s resourceValuesForKeys:{current application's NSURLPathKey} fromBookmarkData:theData
	set thePath to theDict's objectForKey:(current application's NSURLPathKey)
	set originalObject to FileSystem_Convert_Object_To_NSURL(thePath)
	set locatedOriginalNSURL to (FileSystem_Convert_Object_To_NSURL(originalObject)) as text
	if locatedOriginalNSURL is AliasURLString then
		error "alias self-resolves."
	end if
end FileSystem_Object_Alias_Resolve
on FileSystem_Object_Container(fileSystemObject)
	--https://www.macscripter.net/u/Fredrik71
	--https://macscripter.net/viewtopic.php?id=49262
	--Fails with filenames containing multiple period characters.
	try
		set posixPathOfTheFile to FileSystem_Convert_Object_To_PosixPath(fileSystemObject)
		set sourceText to current application's NSString's stringWithString:posixPathOfTheFile
		set FileSystem_ObjectParentFolder to (sourceText's stringByDeletingLastPathComponent()) as string
		set FileSystem_ObjectParentFolder to FileSystem_Convert_Object_To_NSURL(FileSystem_ObjectParentFolder)
		return FileSystem_ObjectParentFolder
	on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
		error "<FileSystem_Object_Container>" & space & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
	end try
end FileSystem_Object_Container
on FileSystem_Object_Delete(fileSystemObject)
	try
		set fileSystemObject to my FileSystem_Convert_Object_To_NSURL(fileSystemObject)
		set fileManager to current application's NSFileManager's |defaultManager|()
		(fileManager's trashItemAtURL:fileSystemObject resultingItemURL:(missing value) |error|:(missing value))
	on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
		error "<FileSystem_Object_Delete>" & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
	end try
end FileSystem_Object_Delete
on FileSystem_Object_Kind(fileSystemObject)
	try
		fileSystemObject
		set fileSystemObject to my FileSystem_Convert_Object_To_NSURL(fileSystemObject)
		set {theResult, theUTI, theError} to (fileSystemObject's getResourceValue:(reference) forKey:(current application's NSURLTypeIdentifierKey) |error|:(reference))
		if not theResult then error theError's localizedDescription() as text
		set theUTI to theUTI as text
		set AppleScript's text item delimiters to "."
		set theUTI to text item -1 of theUTI
		set AppleScript's text item delimiters to ""
		return theUTI as text
	on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
		error "<FileSystem_Object_Kind>" & space & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
	end try
end FileSystem_Object_Kind
on FileSystem_Object_Name_And_Extension(fileSystemObject)
	try
		set posixPathOfTheFile to FileSystem_Convert_Object_To_NSURL(fileSystemObject)
		set objectName to posixPathOfTheFile's |lastPathComponent|()
	on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
		error "<FileSystem_Object_Name>" & space & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
	end try
end FileSystem_Object_Name_And_Extension
on FileSystem_Object_Name(fileSystemObject)
	try
		set fileSystemObject to FileSystem_Convert_Object_To_NSURL(fileSystemObject)
		set FileSystemObjectName to (fileSystemObject's lastPathComponent) as text
		set theExtensionLength to length of ((fileSystemObject's valueForKey:"pathExtension") as text)
		if theExtensionLength > 0 then set FileSystemObjectName to text 1 thru (-1 * (theExtensionLength + 2)) of FileSystemObjectName
		return FileSystemObjectName
	on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
		error "<FileSystem_Object_Name>" & space & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
	end try
end FileSystem_Object_Name
on FileSystem_Objects_Names(fileSystemObjectList)
	--https://www.macscripter.net/u/Fredrik71
	--https://macscripter.net/viewtopic.php?id=49262
	try
		set fileSystemObjectList to (fileSystemObjectList) as list
		repeat with currentIndex from 1 to length of fileSystemObjectList
			set item currentIndex of fileSystemObjectList to FileSystem_Object_Name(item currentIndex of fileSystemObjectList)
		end repeat
		return fileSystemObjectList
	on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
		error "<FileSystem_Objects_Names>" & space & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
	end try
end FileSystem_Objects_Names

on String_Convert_List_To_String(sourceList, textItemDelimiter)
	try
		set the CocoaArray to current application's NSArray's arrayWithArray:sourceList
		set the CocoaString to CocoaArray's componentsJoinedByString:textItemDelimiter
		return (CocoaString as string)
	on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
		error "<String_Convert_List_To_String>" & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
	end try
end String_Convert_List_To_String
on String_Text_Items_Of(aString, aDelimiterList)
	try
		set aString to aString as text
		set previousDelimiters to String_TID_Swap(aDelimiterList)
		set theResults to text items of aString
		set AppleScript's text item delimiters to previousDelimiters
		return theResults
	on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
		error "<String_Text_Items_Of>" & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
	end try
end String_Text_Items_Of
on String_TID_Swap(theDelimiterList)
	--Usage:Include the following lines or similar in your code to change, store, and then restore the previous TIDS
	--set previousDelimiters to String_TID_Swap(theDelimiterList)
	--<your code using the TIDS>
	--String_TID_Swap(previousDelimiters)
	copy AppleScript's text item delimiters to previousDelimiters
	try
		set AppleScript's text item delimiters to theDelimiterList
		return previousDelimiters
	on error errorText number errornumber partial result errorResults from errorObject to errorExpectedType
		error "<String_TID_Swap>" & errorText number errornumber partial result errorResults from errorObject to errorExpectedType
	end try
end String_TID_Swap
1 Like

Glad to see you guys have been working on this. Thanks.

On my end, I’m finding that all three of the new scripts (including the latest on 9/10), do NOT find any broken aliases. But, retesting the old one (by wch1zpink on 5/15/21), I find that it still consistently does find the broken aliases.

So far, I’ve only been testing on folders of a few aliases that have one potentially complicating feature: the folders, broken aliases, and original files all live in my locally synched Dropbox folder. I have not tried testing the script on my whole boot drive, which I suppose might find other more “normal” aliases.

I think step one of testing these needs to be the creation of a known positive. Dupe a folder to your desktop, create an alias to it and then delete the folder. Empty the trash (don’t skip this step). Test the script on your desktop folder and see if it reports the known-broken alias.

The fact that these broken aliases are in a Dropbox folder tells me your problem. Dropbox does not support aliases in either the normal or file provider versions of their app. When Dropbox encounters an alias it syncs it as a normal file 0k in size. Nothing of the alias is uploaded. Those aren’t broken aliases at this point, just broken files.

If you want to resolve those aliases you may have to do so manually, or with an alternate version of one of the scripts in this thread modified to just iterate through your once-aliases and search for their original files by name and re-make the aliases. If you want those aliases original files to sync to Dropbox you’ll have to duplicate them to their aliases original Dropbox location.

Yes, your script does work on (freshly broken) aliases to files on my desktop. Conversely, it does not see old broken aliases that I move from my Dropbox folder to the desktop.

FWIW, If I repair a broken “alias” file in Dropbox (using the old script), I can move it back and forth to my desktop and it works either way. Also, I just remembered that the Finder’s “Get Info” window gives an option to “Select New Original” and that works very much like the old script (but apparently by fixing the alias file rather than trashing and replacing it).

Despite whatever voodoo Dropbox might be doing behind the scenes, its handling of alias files is mostly quite robust. For example, I have my Dropbox folder locally synched on multiple computers, when I repair an alias on one, the synched repaired alias points to the original on the other, just like I want.

So, for now, I’m left with two decent ways to repair aliases in my Dropbox folder, one involving wch1zpink’s old script and the other using Finder’s get info, but both operate on one alias at a time. I still would love to get the batch processing efficiency of paulskinner’s latest script, if there was some way to get it to recognize aliases the way wch1zpink’s does.