Script for opening an indexed file or folder/group in DEVONthink from an external app (e.g., Finder, Alfred, HoudahSpot, etc.)?

Does anyone have a script that they can share that will open an indexed file or folder/group in DEVONthink from an external app, such as Finder, Alfred, HoudahSpot, etc.?

For the most part, my databases in DEVONthink are comprised of indexed files and folders/groups. Often when I come across files or folders in Finder, I’d like to quickly open them in DEVONthink (i.e., without slowly navigating to them again in DEVONthink). Does anyone have a script for doing this (e.g., to be trigged from the MacOS script menu, services, Alfred, etc.)? By analogy, I was thinking it might operate like DEVONthink’s “Show in Finder” - except now I’d like to “Show in DEVONthink” from an external app. To be clear, I understand that it’s a lot more complicated than this, given the potential differences in file hierarchy between Finder and the DEVONthink database where the file/folder/group’s info is located. I only mean to use this as an example.

As you can tell, I’m new to DEVONthink. I tried cobbling together scripts from various forum posts, but each seemed to force a file import. The only solution that I could come up with wasn’t very functional (way too use use-specific, as it assumed a uniform file hierarchy, database, etc.).

Thanks for any help you can lend!

I believe that Alfred can search and open any item in DT directly. But you may want to check their site and download the trial. No script is needed for ur purpose - I think.

See this post on the Alfred forum.

Stephen

Hi @Stephen_C & @ngan - Thanks for getting back to me. I appreciate your help!

I probably wasn’t clear in my initial question/post. I’m looking for a way to open an indexed file or folder from Finder directly in DEVONthink.

For example, let’s say I’m in Finder, in a folder called “Articles” that is indexed by DEVONthink where I have a ton of PDFs stored for various academic articles. And, within that folder I have other folders for specific authors (e.g., Author 1, Author 2, etc.), which also contain more PDFs. If I was viewing the folder “Author 1” in Finder, how could I efficiently open that same folder/group in DEVONthink? Alternatively, if I was viewing “Article 1.pdf” by Author 1 (found in the Finder folder “Author 1”), how could I efficiently go to that PDF in DEVONthink’s interface (instead of Finder). I assume there has to be an easy way of doing this, instead of trying to manually navigate to it again in DEVONthink? The only reason I raised Alfred and HoudahSpot above is because I can imagine myself wanting to open files (in DEVONthink) from their interfaces, too. And, it would be very easy to apply any Finder-related solution to them. However, I’m looking for a more generic solution.

I’m already aware of how to use Alfred and HoudahSpot to find files that are indexed by DEVONthink (which is what the Alfred discussion was about in that post). My question is how to open the files - after you’ve already found them - directly in DEVONthink? Or, put another way, how do you collect all of the Spotlight/Finder-related metadata from a file or folder to then use that information to quickly identify and open the file/folder/group directly in DEVONthink?

For example, if I find “Article 1.pdf” in Finder, how do I quickly reveal it in DEVONthink (from Finder)? By default, it will open in my default PDF reader. And, if I try opening it with DEVONthink, it will import it (even though it’s already indexed).

There are a handful of people that have built workflows for Alfred that search DEVONthink, and will then open your selection in DEVONthink - such as this great workflow - but these are intended for people that want to (1) search DEVONthink’s databases for what they’re looking for, and then (2) open it up DEVONthink or another native app. In my particular circumstances, because the files/folders are fully indexed by DEVONthink, there isn’t much mystery. It doesn’t make much sense to run a full search for them again either using one of those workflows (i.e., step 1 seems unnecessary, since there should be enough information from the file/folder in Finder to quickly open it in DEVONthink).

Thanks for your help! And, my apologies if the first post wasn’t terribly clear.

Indexed files can’t be found in DEVONthink the way you’re mentioning. When you use a Spotlight search to find a file that is indexed in DEVONthink, it will show you the indexed file in the Finder.

Why don’t you just add the groups to the Favorites in DEVONthink 3? These can be accessed in the Sorter.

@BLUEFROG Thanks for getting back to me! I would add the folders to the favorites, but there’s way too many. In addition, I don’t think you would want to do that for files that are not folders/groups anyways. Perhaps I’m missing something though?

In any case, I feel like I can get pretty close just searching for the file based on its filename (see script below). But this felt really hacky, and still requires me to select the file from the results and reveal it.

tell application "Finder"
	set fileAlias to the selection as alias
	set fileName to name of fileAlias
end tell

set theQuery to "filename:" & fileName

tell application id "DNtp"
	activate
	set search query of viewer window 1 to theQuery
end tell

Isn’t there a better way? How do guys recommend that people open indexed files in DEVONthink from Finder?

Alternatively, on DEVONthink’s blog, it praises the use of HoudahSpot’s search - which I can vouch for, is great - but after HoudahSpot finds the indexed file that you’re looking for, how do you open it in DEVONthink?

My take on the task:
The script will open a doc window for a selected file and a main window for a selected folder, and return with a “not in DT” if the selected file/folder is not index in DT.

with three disclaimers:
(1) I never script outside DT so I don’t know how to attach a script to a service or to other apps at MacOS level. But the script works when it is running from script editor.
(2) Use test data even if you dare to try this script.
(3) It’s better to wait for other more experience members for higher quality help. I’m just a beginner.
(4) I wonder why don’t you just use DT as your file manger for the most frequently accessed file (by index them into DT).

anyway, the “suggested” script. (EDITED I changed to a cleaner version of script - I think)

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

tell application "Finder"
	set theSelection to selection as alias list
end tell

if theSelection ≠ {} then
	set theFile to first item of theSelection
	set theFilePath to POSIX path of (contents of theFile)
end if

tell application id "DNtp"
	try
		set theRecords to (lookup records with path theFilePath in current database) -- use current database if there is only one databse, OR use  exact database name as "name" instead of current database
		if theRecords is not {} then
			set theRecord to first item of theRecords

			if type of theRecord is group then
				open window for record theRecord
				return
			else
				open tab for record theRecord
				return
			end if

		else
			display alert "the file/group does not exist in the current DT database"
		end if
	end try
end tell
1 Like

How do guys recommend that people open indexed files in DEVONthink from Finder?

This is not a common thing to do in my experience. I’d have to think on this as it’s an unusual request and I don’t think the search is a good option.

1 Like

@ngan Thank you so much for taking a stab at this! This works great for what I need. Thanks a ton!

I’m going to tinker with the script a little (for my own use cases), and then I’ll repost it for other newbies like myself. Thanks again!

Also, thank you @BLUEFROG for taking a look at it, too. I’ve been called worse things than “unusual” :grin:

I wrote, and posted this script in the old forum, a long long time ago (searching the forum for prior solutions is always a good idea). I still use it. When I forget whether I’ve imported a document to DEVONthink or not, I invoke a Keyboard Maestro macro that runs this simple script. It doesn’t add the item link to the list, but that’s an easy enhancement.

(*
this script requires Keyboard Maestro -- the script operates inside a KM macro
that loops through a selection of files in Finder, and for each file the macro
checks to see if that file can also be found in the current database of
DEVONthink
*)

tell application id "DNtp"
	
	tell application "Keyboard Maestro Engine"
		set i_fileName to value of variable "thisFileName"
	end tell
	
	set allDatabases to every database
	
	set t_fnd to {}
	set for_ to "Looked in open databases for: " & return & i_fileName & return & "---" & return
	
	
	-- set t_fnd to search i_fileName within titles
	-- set t_URL to the reference URL of the first item of t_fnd
	
	repeat with thisDatabase in allDatabases
		set t_fnd to (contents of thisDatabase whose name is i_fileName)
		
		set for_ to for_ & "In: " & name of thisDatabase & return
		set locList to ""
		
		if t_fnd is not equal to {} then
			repeat with thisItem in t_fnd
				set locList to locList & location of thisItem & name of thisItem & return & return
			end repeat
		else
			set locList to "Nothing found" & return & return
		end if
		
		set for_ to for_ & locList
		
	end repeat
	
	return for_
	
end tell
1 Like

:stuck_out_tongue: So have I… so. have. I. :wink:

1 Like

Thanks to everyone’s help, and a lot of tinkering, I feel like I’m getting pretty close, but I’m still stuck on a few small things. In short, I’d like to create two versions of the script: (1) that opens the file or group in DEVONthink’s current viewer window (selecting/highlighting the file and previewing it, or in the case of groups, showing their contents), and (2) another that reveals the file or group, similar to how “reveal” works from the context menu of a search result.

Unfortunately, with both scripts, I keep getting hung up on two core things:

First, is it possible to get @ngan’s wonderful script to search all databases? I only have one big database, and two relatively small ones, but I’d love to be able to search all of them at once, similar to @korm’s great KM script. I tried just setting a variable for them, which works well when you just want to open the file. However, I can’t seem to get it to work when you want to reveal the file in your current viewer window

In any event, here’s a copy of the “reveal” script (the second one from above), which combines aspects of @ngan and @korm’s scripts. It will reveal files and groups appropriately, but doesn’t seem to search every database:

tell application "Finder"
	set theSelection to selection as alias list
end tell

if theSelection ≠ {} then
	set theFile to first item of theSelection
	set theFilePath to POSIX path of (contents of theFile)
end if

tell application id "DNtp"
	try
		set theDatabases to databases
		set theResults to {}
		repeat with thisDatabase in theDatabases
			set thisDatabasesResults to lookup records with path theFilePath in thisDatabase
			set theResults to theResults & thisDatabasesResults
		end repeat
		if theResults = {} then
			display notification "Pfad nicht in offenen Datenbanken enthalten!" with title "Lookup DEVONthink"
			return
		else
			set root of viewer window 1 to (parent 1 of item 1 of theResults)
			set selection of viewer window 1 to theResults
			activate
		end if
	end try
end tell

As for the second problem, I could never get the “open” script from above to properly open the file or folder/group in the current DEVONthink viewer window. In other words, I couldn’t figure out how to adapt @ngan’s script so that instead of opening a new window, that it would do something similar in the viewer window that’s already open.

As always, thanks for any help you can lend. I’d be completely lost without everyone’s support. Also, apologies if I’ve butchered any DEVONthink verbiage above (or the English language, for that matter - Ha). Thanks again!

I only have a quick look at the script and my beginners’ comment as follows:

(1) remind you that DT only look up records in “databases” that are opened. So u need to make sure that all databases remain opened when u run the script or the script will only search in the currently opened database.

(2) logic: if file/s are index into different databases and your script is telling the viewer window to display the file/group in current window. And if you have more than one records in theResults (or same finder’s file in different databases), the script won’t know which one or where to open? You will need to look into the variable theResults to see what items have you retrieved by using the lookup command (I rarely used it) to get a better feel. Use “script debugger” with a free trial period for 15 days (I think) for debugging. The app can run script step-by-step and show the values/records/items in each var in the process in a user-friendly manner.

(3) if you have tagged ur item/s in DT, parent 1 of theResults can be a tag or a group (AFAIMA, there is no fixed rule to determine which one is parent 1, probably based on the time of the creation of each replicant?). That’s why I open a document window for theResults. You may need some code to find all parents of theResults and find the first Parents n that is a group. (This I am not 100% sure)

Might it be possible (via script) for DT to cache a list of all indexed files in a database on close or modification? Then the script can read that file to find files that aren’t open.

@ngan Thanks a ton for the helpful feedback. My intention was to only use the script with one file at time (via a file action in Alfred, which I’ve restricted to a single input). However, you hit the nail on the head with your third point! That explains the weird behavior that I noticed with the “reveal” script that I posted above. In short, occasionally it will errantly reveal the file or group in the Sidebar’s Tags (Globals section) or from the Favorites section (when the group is also located there). Do you know how to restrict it to only selecting the parent (group) from the Open Databases section?

Thanks again to everyone for all of your help!

@korm would have suggested to learn the trick by reading the dictionary or from other script… (for good intention).

Look for one line of code in this post as a starting point?

Find & Goto parent groups of all replicants of an item

1 Like

Take a look at A script library to get the path of the frontmost document

And maybe this Script: Open DEVONthink record for PDF Expert tab

1 Like

@pete31 - Thanks for your help. Ironically, your PDF Expert script was super helpful for fixing a different issue. I created a far more simplistic version of your script a few years ago to work with Alfred for shifting between active PDF documents (PDF Expert, Preview, Adobe Acrobat). I could never figure out how to do it efficiently with PDF Expert (because of its lack of Apple Script support) without running it through Alfred’s search, which never worked particularly well (because it was GUI-based). In any case, your solution with PDF Expert was genius (LSOF - etc.)! It completely solved that problem. Now that script works amazing!

As for this issue, while I’m probably overlooking something, it’s the later part of the problem that I’m struggling with (i.e., how to reveal what you’ve found). Instead of opening the file in DEVONThink, how do I consistently reveal it in the same active window (without opening a new window)? The script that I posted above works in most situations, but will sometimes select the file from the sidebar if its group is located in the Tags or Favorites sections (not the Open Databases section, where it should). Any ideas how to get it to reveal the file or group (instead of open it)?

Thanks again to everyone for all of their help!

This version shows the contents of a group or previews a record

-- opens the file or group in DEVONthink’s current viewer window (selecting/highlighting the file and previewing it, or in the case of groups, showing their contents)

tell application "Finder"
	set theSelection to selection as alias list
end tell

if theSelection ≠ {} then
	set theFile to first item of theSelection
	set theFilePath to POSIX path of (contents of theFile)
end if

tell application id "DNtp"
	try
		set theDatabases to databases
		set theResults to {}
		repeat with thisDatabase in theDatabases
			set thisDatabasesResults to lookup records with path theFilePath in thisDatabase
			set theResults to theResults & thisDatabasesResults
		end repeat
		if theResults = {} then
			display notification "Pfad nicht in offenen Datenbanken enthalten!" with title "Lookup DEVONthink"
			return
		else
			
			set theRecord to (item 1 of theResults)
			
			if type of theRecord = group then
				set root of viewer window 1 to theRecord
				set selection of viewer window 1 to theRecord
				activate
			else
				set root of viewer window 1 to (parent 1 of theRecord)
				set selection of viewer window 1 to (theRecord as list)
				activate
			end if
			
		end if
	end try
end tell

And this reveals a record

-- reveals the file or group, similar to how “reveal” works from the context menu of a search result

tell application "Finder"
	set theSelection to selection as alias list
end tell

if theSelection ≠ {} then
	set theFile to first item of theSelection
	set theFilePath to POSIX path of (contents of theFile)
end if

tell application id "DNtp"
	try
		set theDatabases to databases
		set theResults to {}
		repeat with thisDatabase in theDatabases
			set thisDatabasesResults to lookup records with path theFilePath in thisDatabase
			set theResults to theResults & thisDatabasesResults
		end repeat
		if theResults = {} then
			display notification "Pfad nicht in offenen Datenbanken enthalten!" with title "Lookup DEVONthink"
			return
		else
			
			set theRecord to (item 1 of theResults)
			
			set root of viewer window 1 to (root of (database of theRecord))
			set selection of viewer window 1 to (theRecord as list)
			activate
			
		end if
	end try
end tell

For testing I used a folder which I indexed in two databases but without tagging or replicating the group. It seems the scripts will always use the record in the database that was last used.

Have you tried the script library? With this it’s possible to open a DEVONthink record from a lot of apps, not only Finder

2 Likes

@pete31 Thanks a ton! These scripts are amazing, and I can now see what I was screwing up in the “reveal” script previously. I can’t thank you enough!

In the reveal script, by chance, is it possible to have DEVONthink select the parent folder/group in the Sidebar, too? At the moment, it selects the database - which fixes the problem I mentioned above about errantly selecting from the Tags or Shortcuts sections of the Sidebar - however, it doesn’t drill down any further in the Sidebar to let the user know they’re at in the hierarchy (based on the Sidebar alone - i.e., obviously you can still see it in the main window, however).

While I understand that you can’t select the actual file or group in the Sidebar (or else it would open the group, instead of just revealing it), I like the idea of quickly seeing where I’m at from the Sidebar by at least selecting its parent folder. In addition, it also makes it easier to subsequently run a search on a group that is in close proximity to the file/group you just revealed (which, in DT3, from what I understand, always requires you to actually select the group in the sidebar).

To accomplish this, I tried adding the “parent” line from your “open” script, but that didn’t change it’s end result:

		set theRecord to (item 1 of theResults)
		set root of viewer window 1 to (parent of (database of theRecord)) -- ADDED !!
		set root of viewer window 1 to (root of (database of theRecord))
		set selection of viewer window 1 to (theRecord as list)
		activate

The hope was that it would first select the parent folder/group from the sidebar, leaving it expanded, before revealing the actual file/group. However, it seems to behave the same way (never expanding the database from sidebar). Is this possible?

I haven’t tried your script library yet. It’s probably a little beyond my skill set at the moment (AppleScript and DEVONthink). However, I’ll definitely take a look at it now!!! Thanks for sharing! Another part of the reason that I haven’t, is that I’m not quite as dependent on Finder, as this script might seem. I included Finder because I felt like it would be most helpful for other DT newbies, like myself. In fact, I’m still pretty surprised there isn’t a MacOS service included in DT3 that does the same thing (at least for those who prefer to go the index route, it feels like a must). In any case, as an Alfred user, it’s not as difficult to do similar things from other apps, like HoudahSpot, etc. Thanks again for all of your help!! I really appreciate it.