Replicate or Move selected file to group containing name

This script is for those of you who like me don’t like mousing. I save this script with a command key, and then invoke it to file the selected file in the group(s) matching the phrase I type in. This works great for deeper hierarcies.

The script will give you a list of all groups that contain your search phrase, and it will look for them in all open databases. Whatever folders match, it will display the path to them, and you can choose one or more to replicate to, so long as they are in the same database. Moving files between databases works well with this script as well.

enjoy!
Erico

Script below updated 9-9-09


----replicate to named group 
--by Eric Oberle v 1.2
--This script assumes you have selected a group of records. 
---It then will replicate those records to a folder of your choosing.
----It will attempt to locate this folder based on a string search of all folders in all currently open databases.  
---It searches all open databases, and if the chosen destination is in another database, the script will move the record to that database

--this script requires Mac Growl to be installed for notifications.

tell application "DEVONthink Pro"
	
	set db to current database
	set dbn to get name of db
	log (dbn as text)
	set safe_sel to {selection}
	if safe_sel is not application then
		set cur_sel to selection
		set first_item to first item of cur_sel
		set rec_name to name of first_item
	else
		display dialog "please select an item"
	end if
	
	---prompt user for records to search
	set the_filter to "*"
	set the_filter to display dialog "Please enter a portion of the destination to which you would like to replicate the selected records:  " & rec_name default answer "*"
	set the_filter to text returned of the_filter
	set combined_record_list to my records_matching_name(the_filter)
	
	--build list of hierarchical names
	set combined_name_list to my build_hierarchical_list(combined_record_list)
	
	
	if (count of combined_name_list) is greater than 0 then
		set destination_list to my choose_record_from_name_list(combined_name_list, combined_record_list)
		
		repeat with the_destination in destination_list
			--		set the_destination to item (this_target) of record_list
			log "about to replicate" & name of the_destination
			
			repeat with the_rec in cur_sel
				--duplicate record the_rec to the_destination
				set the_rep to replicate record the_rec to the_destination
				set cur_group to current group
				
				log the_rep
				if the_rep is missing value then
					---duplicate the record if replicating fails
					---(It probably failed because the destination is in a different database than the target, so export the record.) 
					log "detected missing value"
					duplicate record the_rec to the_destination
					
					move record the_rec to the_destination from cur_sel
					
					(* following code exports and then reimports
					
					set the_export to export record the_rec to "/tmp/"
					import the_export to the_destination
					my growlNotification("DEVONthink Pro", "duplicated" & name of the_rec & " to", name of the_destination)
					
					log (do shell script ("rm -r " & quoted form of the_export))
					*)
				else
					my growlNotification("DEVONthink Pro", "replicated " & name of the_rep, name of the_destination)
					
				end if
			end repeat
		end repeat
		
	else
		---if we didn't find the destination, allow user to create it.
		beep
		set new_folder to display dialog "Destination not found. To create a new group please ennter it here or cancel to exit:  " & rec_name default answer the_filter
		set new_folder to text returned of new_folder
		---prompt user for records to search
		
		set the_filter to display dialog "We are now going to search for the destination of the new group " & new_folder & ". Please enter a partial name." default answer "*"
		set the_filter to text returned of the_filter
		
		set combined_record_list to my records_matching_name(the_filter)
		
		--build list of hierarchical names
		set combined_name_list to my build_hierarchical_list(combined_record_list)
		
		
		if (count of combined_name_list) is greater than 0 then
			set destination_list to my choose_record_from_name_list(combined_name_list, combined_record_list)
			repeat with this_destination in destination_list
				set new_record to create record with {type:group, name:new_folder} in this_destination
				repeat with the_rec in cur_sel
					set the_rep to replicate record the_rec to new_record
				end repeat
			end repeat
		end if
		
	end if
	
	
end tell



on choose_record_from_name_list(name_list, record_list)
	---given two lists--a list of names and a list of records that are equal in length and
	--corresponding to each other, this subroutine asks the user to pick from the name list
	---and returns the corresponding record(s)
	set destination_records to {}
	set destination_numbers to {}
	tell application "DEVONthink Pro"
		set user_choice to choose from list name_list with multiple selections allowed
		log user_choice
		
		if user_choice is {} then
			return {}
			
		else
			
			---choose item returns the string they actually chose....
			---so recurse through list again to figure out which item that was
			set the_choices to every item of user_choice
			log the_choices
			log item 1 of the_choices
			repeat with this_choice in the_choices
				set the_counter to 0
				repeat with this_record in name_list
					set the_counter to the_counter + 1
					log "comparing " & this_choice & " to " & this_record & return
					if this_record contains this_choice or this_record is equal to this_choice then
						set destination_numbers to destination_numbers & {the_counter}
						set the_dest to item (the_counter) of record_list
						
						set destination_records to destination_records & {the_dest}
						--		set the_destination to item (this_target) of record_list
						log "found match"
					end if
				end repeat
			end repeat
			return destination_records
		end if
	end tell
end choose_record_from_name_list


on records_matching_name(the_string)
	tell application "DEVONthink Pro"
		set record_list to {}
		set the_dbs to get databases
		repeat with this_db in the_dbs
			set record_list to record_list & (every parent of this_db whose name contains the_string)
		end repeat
		return record_list
	end tell
end records_matching_name


on build_hierarchical_list(the_records)
	set name_list to {}
	if the_records is not {} then
		repeat with this_rec in the_records
			set hier_name to my name_hierarchy(this_rec, "", true)
			set name_list to name_list & hier_name
		end repeat
	end if
	return name_list
end build_hierarchical_list


on name_hierarchy(the_record, previous_parent, even_time_in)
	---uses recursion to create a string describing the "path" of the record....
	----this seems to be the only way to figure out the internal database path of a given record.
	---I can at least see no other method that works to discover the database to which a record belongs. 
	
	tell application "DEVONthink Pro"
		set the_string to ""
		set the_name to ""
		set x to get name of the_record
		log x
		set y to get kind of the_record
		log y
		log (count of parents of the_record)
		
		
		log {first parent of the_record}
		
		if (count of parents of the_record) is greater than 0 then
			set parent_name to name of first parent of the_record
			
			log "recursing " & name of the_record & " ** " & the_name
			if even_time_in is true then
				set the_name to "==>" & name of the_record
				set the_name to my name_hierarchy(first parent of the_record, parent_name, false) & the_name
				
			else
				
				set the_name to my name_hierarchy(first parent of the_record, parent_name, true) & " -> " & previous_parent & the_name
				
			end if
			
		else
			log "about to return " & the_name
			return previous_parent & the_name
		end if
		return the_name
	end tell
	
end name_hierarchy


on growlNotification(growlIcon, growlTitle, growlDescrip)
	
	if application "GrowlHelperApp" is running then
		set appName to "ericsdtnotify"
		set notifs to {growlTitle}
		
		tell application "GrowlHelperApp"
			register as application ¬
				appName all notifications notifs ¬
				default notifications notifs ¬
				icon of application growlIcon
			notify with name growlTitle title growlTitle description growlDescrip application name appName
		end tell
	end if
	return ""
end growlNotification

Great script, thanks for that, erico.

It highlights one of the major weaknesses of DT’s GUI: the lack of a fast, efficient, keyboard-supported way to clean up inboxes, i.e. to move/replicate and, soon, tag dozens or even hundreds of records.

Mail Act-On from indev.ca is pretty efficient for filing records by keyboard

Thanks! I agree with andreas on the lack of keyboard shortcuts to clean up the inboxes.

Hey Erico,

Great script - very useful indeed!
I love it - just made a small mod to stop the duplication of records when they are moved to a new database - I removed the line “duplicate record the_rec to the_destination”

This way it fits in better with my billing workflow for keeping track of my tasks from OmniFocus (it used to duplicate the record when it was left in)

  • OmniFocus ---- (applescript SaveToDevon from this site: web.mac.com/robinfrancistrew/Sit … think.html) —> DT in a intermediate database (OmniFocus Notes)
  • All Editing and notetaking done in DT for this task
  • When I’m finished I invoke your script to move it to a Group ‘Done’ in the relevant Client DT database (where I store all work for that particular client).
  • I then get the DT link for this record and store in the OF notes for the task (easy to click to get back to the task later on)
  • I also use OF to keep timetracking info for billing

I can do all this without mousing around.
It’s a great personal knowledge bank.

sends Erico a slab of beer for making my life easier! :slight_smile:

Namaste,
CaptainB