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

it does! thank you so much! one more question, how does punctuation work when it comes to matching text to tags? for example - if my tag is “barbour county, alabama” and the text of a document says “barbour county alabama” will that be a match? what about the opposite scenario - no punctuation in the tag but punctuation in the text?

I guess both won’t match.

thanks pete! is there a way to ignore punctuation when matching? if not no worries, i just thought i’d check. Thanks!

No. But adding an alias without (or with) the punctuation should work.

but if i add an alias with a comma, won’t it recognize that as two separate tags instead of one whole one?

Ahh, yes, of course.

Mixed things up with this thread Tags with comma.

yes, i really wish there was a workaround for this! would be great if quotation marks worked, or a semi-colon separated tags instead of a colon.

i don’t know who to tag but it seems like it would be right to either be able to use punctuation in aliases or have the tag matching function ignore punctuation?

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