Script: Assign selected tag to matching records based on content and name

question about the original script in this thread, pete - does it only find the matching phrase, or will it match if both words are in the document regardless? so if i want it to find “red dog” will it only find “red dog” or will it tag red dog if it finds both red and dog? i’m hoping for the former but sometimes it seems to do the latter for some reason. could be my mistake though so wanted to check. thank you!

It only matches for red dog, not for red some other text dog. It’s the same behaviour as DEVONthink’s Smart Rule script “Assign tags”.

excellent

1 Like

@pete31 i want to thank you again for this script - it’s saved me HOURS of work. can’t tell you how grateful i am.

1 Like

Great to hear that :slight_smile:

@pete31 is there a way to do this exact same thing but find and tag all instances in all open databases?

If you remove in theSearchScope then all databases will be searched:

set theResults to search theQuery

sorry, i see a couple of places where set the search scope is so i need a littel more guidance. my apologies!

No problem. This is not tested but should do it

-- Assign selected tag to matching records based on content and name 

property includeNameInSearch : true -- if false only text is searched

tell application id "DNtp"
	try
		set theTagRecords to selected records
		if theTagRecords = {} then error "Please select some tags."
		
		show progress indicator "Tagging... " steps (count theTagRecords) as string with cancel button
		
		repeat with thisRecord in theTagRecords
			if (location of thisRecord) starts with "/Tags/" then
				
				set thisRecord_Name to name of thisRecord
				step progress indicator thisRecord_Name
				set thisRecord_Aliases to aliases of thisRecord
				set theNames to {thisRecord_Name} & my tid(thisRecord_Aliases, {", ", "; ", ",", ";"})
				set theNames_readyForQuery to "\"" & my tid(theNames, "\" OR \"") & "\""
				
				if includeNameInSearch = true then
					set theQuery to "tags!=" & thisRecord_Name & " kind:any {any: name:" & theNames_readyForQuery & " text:" & theNames_readyForQuery & "}"
				else
					set theQuery to "tags!=" & thisRecord_Name & " kind:any text:" & theNames_readyForQuery
				end if
				
				set theResults to search theQuery
				
				repeat with thisResult in theResults
					set tags of thisResult to (tags of thisResult) & thisRecord_Name
				end repeat
				
			end if
		end repeat
		
		hide progress indicator
		
	on error error_message number error_number
		hide progress indicator
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
		return
	end try
end tell

on tid(theInput, theDelimiter)
	set d to AppleScript's text item delimiters
	set AppleScript's text item delimiters to theDelimiter
	if class of theInput = text then
		set theOutput to text items of theInput
	else if class of theInput = list then
		set theOutput to theInput as text
	end if
	set AppleScript's text item delimiters to d
	return theOutput
end tid

incredible! thank you! my only question - just now i tagged something with a new tag with an alias, e.g. “Jane doe” with the alias jane r. doe. the other databases created a tag (amazing!) but it didn’t include the alias in the other databases. is there a way i can do that easily? thank you so much for all of your incredible help.

This should do it, didn’t test.

-- Assign selected tag to matching records based on content and name 

property includeNameInSearch : true -- if false only text is searched

tell application id "DNtp"
	try
		set theTagRecords to selected records
		if theTagRecords = {} then error "Please select some tags."
		
		show progress indicator "Tagging... " steps (count theTagRecords) as string with cancel button
		
		repeat with thisRecord in theTagRecords
			set thisRecord_Location to location of thisRecord
			if thisRecord_Location starts with "/Tags/" then
				
				set thisRecord_Name to name of thisRecord
				step progress indicator thisRecord_Name
				set thisRecord_Aliases to aliases of thisRecord
				set theNames to {thisRecord_Name} & my tid(thisRecord_Aliases, {", ", "; ", ",", ";"})
				set theNames_readyForQuery to "\"" & my tid(theNames, "\" OR \"") & "\""
				
				if includeNameInSearch = true then
					set theQuery to "tags!=" & thisRecord_Name & " kind:any {any: name:" & theNames_readyForQuery & " text:" & theNames_readyForQuery & "}"
				else
					set theQuery to "tags!=" & thisRecord_Name & " kind:any text:" & theNames_readyForQuery
				end if
				
				set theResults to search theQuery
				
				if theResults ≠ {} then
					
					set thisRecord_Database to database of thisRecord
					if thisRecord_Name contains "/" then
						set thisRecord_LocationAndName to (thisRecord_Location & (my escapeSlash(thisRecord_Name)))
					else
						set thisRecord_LocationAndName to (thisRecord_Location & thisRecord_Name)
					end if
					
					repeat with thisResult in theResults
						if thisRecord_Database ≠ (database of thisResult) then
							set thisTag to create location thisRecord_LocationAndName in database of thisResult
							set aliases of thisTag to thisRecord_Aliases
						end if
						set tags of thisResult to (tags of thisResult) & thisRecord_Name
					end repeat
					
				end if
				
			end if
		end repeat
		
		hide progress indicator
		
	on error error_message number error_number
		hide progress indicator
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
		return
	end try
end tell

on tid(theInput, theDelimiter)
	set d to AppleScript's text item delimiters
	set AppleScript's text item delimiters to theDelimiter
	if class of theInput = text then
		set theOutput to text items of theInput
	else if class of theInput = list then
		set theOutput to theInput as text
	end if
	set AppleScript's text item delimiters to d
	return theOutput
end tid

on escapeSlash(theText)
	set d to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "/"
	set theTextItems to every text item of theText
	set AppleScript's text item delimiters to "\\/"
	set theText_escaped to theTextItems as string
	set AppleScript's text item delimiters to d
	return theText_escaped
end escapeSlash

1 Like

you’re the best thank you thank you

1 Like

hey @pete31 - i saw your other script where you could use the assign tags function but ignoring punctuation. i love that, and was wondering if such a thing could exist here. so if i wanted to, for example, find everything with the text “mcpherson county, kansas” and tag it as such, with the alias: “mcpherson county ks”, what i’d like to do is ensure the alias will also search for “mcpherson county, ks” with the comma, and tag it as such. that way i don’t have to worry about commas in aliases. but i don’t know if that’s possible - or if this makes sense.

@josieduffy to be honest I lost track of what all these tag scripts do. Could you explain what you need? Would that all go into one script? And do you need a normal script or a Smart Rule script?

its actually not important because i found out that an alias of, lets say, “washington dc” also finds “washington, dc” so we’re good!

1 Like

this script, which assigns the selected tags to matching records across all open databases, is amazing. i use it all the time. but i was wondering if you had any ideas re: why it’s running really slowly lately - no other script is running slowly, its still the exact same databases open that i used before, but in the past week or so it runs at a snails pace. is there anything i can do about that? no program is taking up too much cpu or anything. i just am not sure how to address it. thanks! tagging @pete31 since he so kindly developed it

Which one? I really lost track. Don’t want to read the whole thread or guess what we‘re talking about. Could you please link to the post you‘re referring to?

No idea. I‘ll check this.

here it is!

Try this. No idea whether that makes a difference.

-- Assign selected tag to matching records based on content and name 

property includeNameInSearch : true -- if false only text is searched

tell application id "DNtp"
	try
		set theTagRecords to selected records whose location starts with "/Tags/"
		if theTagRecords = {} then error "Please select some tags."
		show progress indicator "Tagging... " steps (count theTagRecords) as integer with cancel button
		
		script s
			property theRecordList : missing value
			property theResultList : missing value
		end script
		
		set s's theRecordList to theTagRecords
		
		repeat with thisRecord in s's theRecordList
			set thisRecord_Location to location of thisRecord
			set thisRecord_Name to name of thisRecord
			step progress indicator thisRecord_Name
			set thisRecord_Aliases to aliases of thisRecord
			set theNames to {thisRecord_Name} & my tid(thisRecord_Aliases, {", ", "; ", ",", ";"})
			set theNames_readyForQuery to "\"" & my tid(theNames, "\" OR \"") & "\""
			
			if includeNameInSearch = true then
				set theQuery to "tags!=" & thisRecord_Name & " kind:any {any: name:" & theNames_readyForQuery & " text:" & theNames_readyForQuery & "}"
			else
				set theQuery to "tags!=" & thisRecord_Name & " kind:any text:" & theNames_readyForQuery
			end if
			
			set theResults to search theQuery
			
			if theResults ≠ {} then
				if thisRecord_Name does not contain "/" then
					set thisRecord_LocationAndName to (thisRecord_Location & thisRecord_Name)
				else
					set thisRecord_LocationAndName to (thisRecord_Location & (my escapeSlash(thisRecord_Name)))
				end if
				
				set s's theResultList to theResults
				
				repeat with thisResult in s's theResultList
					set thisResult_Database to database of thisResult
					if database of thisRecord ≠ thisResult_Database then
						set thisTag to create location thisRecord_LocationAndName in thisResult_Database
						set aliases of thisTag to thisRecord_Aliases
					end if
					set tags of thisResult to (tags of thisResult) & thisRecord_Name
				end repeat
				
			end if
		end repeat
		
		hide progress indicator
	on error error_message number error_number
		hide progress indicator
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
		return
	end try
end tell

on tid(theInput, theDelimiter)
	set d to AppleScript's text item delimiters
	set AppleScript's text item delimiters to theDelimiter
	if class of theInput = text then
		set theOutput to text items of theInput
	else if class of theInput = list then
		set theOutput to theInput as text
	end if
	set AppleScript's text item delimiters to d
	return theOutput
end tid

on escapeSlash(theText)
	set d to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "/"
	set theTextItems to every text item of theText
	set AppleScript's text item delimiters to "\\/"
	set theText_escaped to theTextItems as string
	set AppleScript's text item delimiters to d
	return theText_escaped
end escapeSlash