Hazel rule script for importing/indexing to a specific group

The script in this posting is deprecated. Scroll down this thread and see the updated script dated July 10, 2013 – five posts below this one

See these topics:

Script to include in a Hazel (3.x) rule to import or index files (or folders) to DEVONthink (2.x). Applies concepts developed by itaiferber and Greg Jones.

Modify the DEVONthink “tell” block:

  1. Obtain the filesystem path for the target database and insert it in place of leaving the quotations: for example “~/Documents/Databases/My Stuff.dtBase2”
  2. Enter the group path (starting at the database root – which is “/”), in place of leaving the quotations. For example “/Imports/My Hazel Docs/”
  3. To import, use the command line beginning “set theImport…”
  4. To index, use the command line beginning “set theIndex…”
  5. Be sure to comment out either #3 or #4 depending on the method, else you will have an undesireable result.

The script will create the group with the given path in the database. If the group already exists, the existing group will be used and a new group will not be created.

WARNING: This script has to have correctly hardcoded database and group paths. If the paths are wrong or the database and/or the group is moved, the script will fail.

-- Get file metadata from Finder.
tell application "Finder"
	set _path to (the POSIX path of theFile as string)
	set _name to (the name of theFile as string)
end tell

-- Lauch DEVONthink if it isn't already open.
tell application "System Events"
	if not (exists process "DEVONthink Pro Office") then
		tell application id "com.devon-technologies.thinkpro2" to activate
	end if
end tell

-- Import the file.

tell application id "com.devon-technologies.thinkpro2"
	set theDatabase to open database "<DATABASE PATH>"
	set theGroup to create location "<GROUP PATH>" in theDatabase
	set theImport to import _path name _name to theGroup
	-- set theIndex to indicate _path to theGroup
end tell

It’s advisable to have Hazel delete items after they are imported – but do NOT have Hazel delete indexed documents :confused:

1 Like

To aid the setup in the first script posted in this thread, here is a little helper script that will put the path of the current database onto the clipboard:

tell application id "DNtp"
	set theDatabasePath to the path of the current database
	display dialog theDatabasePath
	set the clipboard to theDatabasePath
end tell

Korm-

Thanks so much for persisting and clarifying this, for those of us who want to incorporate Hazel into our workflow.

Excellent work!

I wanted to add my experience and results. I wanted to download bills, and have them automatically renamed, based on the service provider and date, both of which are used to rename the file.

I had a few issues getting this to work.

First, if I renamed using a date match taken from the bill, I had Hazel include the extension. Extensions are hidden in my Finder, but if you don’t have Hazel add the extension, the file becomes readable by TextEdit, and nothing shows up upon QuickView. So I added some language to the script to hide the file extension:

-- Hide file extension in Finder

tell application "Finder"
	set extension hidden of theFile to true
end tell

At first, this didn’t work, because I had it in the wrong place. After some experimentation, I found it had to occur first in the script.

Second, I wanted the file imported into a group in DTPO without an extension. Even though DTPO preferences were set to import without a file extension, I suppose the string for the filename included the extension. So I had to come up with a way to remove the extension:


-- Strip extension for path and file name

tell application "Finder"
	-- set theSelection to first item of (get selection)
	set {theName, theExtension} to {name, name extension} of theFile
	-- theSelection
end tell

if theExtension is not "" then
	set theName to text 1 thru -((count theExtension) + 2) of theName -- just the name part
	set theExtension to "." & theExtension
end if

This was set up to work with the rest of Korm’s script.

Third, I wanted to delete the file from Finder after importing it. This is easy with Hazel.


So, Hazel is set up to search the doc for a keyword or two, and then a date. After this, Hazel renames the file based on these two data. Next, Hazel runs the following script, modified slightly from Korm:

-- Hide file extension in Finder

tell application "Finder"
	set extension hidden of theFile to true
end tell

-- Strip extension for path and file name

tell application "Finder"
	-- set theSelection to first item of (get selection)
	set {theName, theExtension} to {name, name extension} of theFile
	-- theSelection
end tell

if theExtension is not "" then
	set theName to text 1 thru -((count theExtension) + 2) of theName -- just the name part
	set theExtension to "." & theExtension
end if

-- Get file metadata from Finder.
tell application "Finder"
	set _path to (the POSIX path of theFile as string)
	set _name to theName
	-- (the name of theFile as string)
end tell


-- Lauch DEVONthink if it isn't already open.
tell application "System Events"
	if not (exists process "DEVONthink Pro Office") then
		tell application id "com.devon-technologies.thinkpro2" to activate
	end if
end tell

-- Import the file.

tell application id "com.devon-technologies.thinkpro2"
	set theDatabase to open database "/Users/Scott/ Documents/Computer/DEVONthink Pro Office Data/Vanguard Specialty
Imaging.dtBase2"
	set theGroup to create location "/Financial/VSI Vendors & Accounts/AT&T Uverse/" in theDatabase
	set theImport to import _path name _name to theGroup
	-- set theIndex to indicate _path to theGroup
end tell

Finally, Hazel moves the original file to the trash.


I’m quite sure Korm or another AS whiz will be able to clean up my patchwork script, but at least it works right now. Please let me know if there are any questions about the date match or renaming in Hazel.

I’m very pleased with the capabilities of Hazel for this purpose, and will definitely set up all my bills to download, auto-rename, and auto-file.

Cheers!

(Thanks again, Korm)

Here I’ve consolidated @sawxray’s concepts and condensed the flow to save approximately 245 nanoseconds in the execution phase :laughing:

(*
Modfied to include concepts proposed by @sawxray
see: https://discourse.devontechnologies.com/t/hazel-rule-script-for-importing-indexing-to-a-specific-group/15941/1
*)

tell application "Finder"
	set _path to (the POSIX path of theFile as string)
	set {_name, _extension} to {name, name extension} of theFile
	
	-- optional: hide extension in Finder
	set extension hidden of theFile to true
	
	-- optional: remove extension for DEVONthink displays
	set _name to text 1 thru -((count _extension) + 2) of _name
	set _extension to "." & _extension
end tell

-- Launch DEVONthink if it isn't already open.
tell application "System Events"
	if not (exists process "DEVONthink Pro Office") then
		tell application id "com.devon-technologies.thinkpro2" to activate
	end if
end tell

-- Import the file.

tell application id "com.devon-technologies.thinkpro2"
	set theDatabase to open database "<database path>"
	set theGroup to create location "<group path>" in theDatabase
	
	-- choose one option, Index or Import, comment out the other
	set theImport to import _path name _name to theGroup
	-- set theIndex to indicate _path to theGroup
end tell

Korm-

You have underestimated your skills yet again. I saved at least 300 nanoseconds!

Seriously, another piece of work from you that is now in my arsenal of daily tools. Kudos to you.

Is this a great forum, or what?

Here is a revised version of the Hazel import script that will find the destination group whether or not the database is open, and even if the group has been moved to another location with a database or moved to another database.

tell application "Finder"
	set _path to (the POSIX path of theFile as string)
	set {_name, _extension} to {name, name extension} of theFile
	
	-- optional: hide extension in Finder
	set extension hidden of theFile to true
	
	-- optional: remove extension for DEVONthink displays
	set _name to text 1 thru -((count _extension) + 2) of _name
	set _extension to "." & _extension
end tell

-- Launch DEVONthink if it isn't already open.
tell application "System Events"
	if not (exists process "DEVONthink Pro Office") then
		tell application id "com.devon-technologies.thinkpro2" to activate
	end if
end tell

-- Import the file.

tell application id "com.devon-technologies.thinkpro2"
	set theGroup to get record with uuid "<group uuid>"
	
	-- choose one option, Index or Import, comment out the other
	set theImport to import _path name _name to theGroup
	-- set theIndex to indicate _path to theGroup
end tell

To set up this version, you need to group’s UUID. To obtain that, click on the target group in DEVONthink being sure to select the group itself and not something inside the group. Then, from the contextual menu, select Copy Item Link. Paste the clipboard contents (the item link) into the script here


set theGroup to get record with uuid "x-devonthink-item://A4BE6367-73A8-41D3-8538-75DCB9D6929C"

edit that to remove the string “x-devonthink-item://” so that the command is now


set theGroup to get record with uuid "A4BE6367-73A8-41D3-8538-75DCB9D6929C"

Much gratitude to Christian for giving me the tip that led to this much more flexible version of the script.

This script has literally just changed my life!! I’ve been using automator workflows (because I don’t know how to use Applescript) to get my scanned documents from my ActionFolder into the various folders in my DTP database but its very clunky and if DTP is not running and in the same space, then it doesn’t always work.

I’ve just updated all my Hazel rules using this script and it is brilliant so thank you.

A related question: is there a way to use scripting so that when a filed is added to a particular group, you can sort it automatically into sub-groups by date (i.e. year). Say you run the script so that every time you scan a bank statement, it gets put into your Bank Statements group in your database - it would be awesome if it added it to a sub-group according to year and if a sub group for the year was not there, it created one.

Hazel can do this but obviously not if you are running the above script to import documents into DTP instead of into a normal vanilla nested folder arrangement outside DTP.

At the moment, my paperless set up has a group for each tax year with sub-groups for each category - bills, bank statements, deductible expenses etc.

Whether with automator or this script, it means editing each Hazel rule each new year to point to the new sub group.

Maybe I would be smarter to have each category and then sub-groups by year underneath as then it would be easy to manually create them at the end of the year just by selecting all the bank statements for the year and grouping them.

Interested to know what others do?

The reason I have it divided by years is that we are required by law to keep tax documents for 5 years but after that I can prune out the old years - either delete or archive so my database doesn’t eventually grow enormous?

Thank you for the detailed notes on setting up the Apple Script.

Is it possible to set the import group as a Smart Group, or just to send it to the database? I don’t want it in the Inbox, so I don’t have to go through and clean it up.

That’s exactly what I do, such that each group (of bank statements or utility bills or whatever) contains the current year’s documents, plus folders titled by year containing previous years’ documents. So there is no need to update the script in Hazel each year. … I always find myself automating things unnecessarily, but this is one case where I feel confident that grouping old documents once a year manually is the easier choice.

It’s quite simple to test both these scenarios, and any others you have in mind: just copy the item link for whatever location you want to import to, insert the UUID into korm’s script, and see what happens.

I found that it doesn’t work for smart groups, which makes sense because a smart group is a live search, not a true location. Try moving an item into a smart group in DEVONthink – it won’t work – so there’s no reason to expect a script to be able to do this either. If your item happens to match the criteria for your smart group, it’ll appear there anyway.

What do you mean by “just send it to the database”? I don’t think you can send an item to the root level of a database, because (as far as I can tell) there is no way to link to the root level. You can, however, send an item to a specific database’s inbox, which you might prefer to the Global Inbox. To do this, just follow korm’s instructions, treating your database’s inbox like any other group.

As mentioned, Smart Groups are saved searches and only have content when you observe them – so no, you can’t send a file to place that doesn’t really exist.

The instructions above explain how to get the UUID of any group in any database. (The point of this script is to import things to specific groups, BTW.) So, no, you don’t have to send the import to the Global Inbox or the Inbox of a database. Get get your destination group’s UUID, plug it into the script, save, and away you go.

If you don’t like the instructions above, then use the following script:

tell application id "DNtp"
	set thisItem to the (first item of (the selection as list))
	if the kind of thisItem is not "Group" then
		display dialog "You need to select a group, not a document"
	else
		set the clipboard to (the uuid of thisItem as string)
	end if
end tell

Copy, paste into Script Editor, select a Group in DEVONthink, run the script. The Group’s UUID is now on the clipboard. If you select a document instead of a Group, the script will abend.

(@dbgeecher – databases do have roots. When you select Go > Top Group you’ll be at the root of that database, where the database’s Inbox and other top level groups reside. If someone needs to find the root UUID let me know and I’ll explain – but that would be kind of a weird thing to want to use in this Hazel technique.)

I have a question regarding the posted script. I am currently trying to get a file with Hazel into DTPO, therefore I have created an AppleScript with the above-mentioned content. When I start the execution, however, I receive the message "error “Die Variable „theFile“ ist nicht definiert.” number -2753 from “theFile” Can anyone help me fixing this issue?

Thanks a lot in advance!

Problem solved, I have choosen the wrong option :unamused:

:mrgreen:

*SOLVED

Hi there,

not knowing anything concerning AppleScript, I try to use the above mentioned script to move pdf files (creditcard bills) with Hazel into a DEVONthink group. I copied the UUID and placed it into the script.

tell application "Finder"
	set _path to (the POSIX path of theFile as string)
	set {_name, _extension} to {name, name extension} of theFile
	
	-- optional: hide extension in Finder
	set extension hidden of theFile to true
	
	-- optional: remove extension for DEVONthink displays
	set _name to text 1 thru -((count _extension) + 2) of _name
	set _extension to "." & _extension
end tell

-- Launch DEVONthink if it isn't already open.
tell application "System Events"
	if not (exists process "DEVONthink Pro Office") then
		tell application id "com.devon-technologies.thinkpro2" to activate
	end if
end tell

-- Import the file.

tell application id "com.devon-technologies.thinkpro2"
	set theGroup to get record with uuid "E2819D1A-8817-43AC-9514-56FFFA217857"
	
	-- choose one option, Index or Import, comment out the other
	set theImport to import _path name _name to theGroup
	-- set theIndex to indicate _path to theGroup
end tell

-- that here is important
return true

Unfortunately I do receive the following error


At least one of the actions has an empty field or an error. Please fill in the field, correct the error or remove the action

and in the Hazel preview this


Invalid AppleScript return value: <NSAppleEventDescriptor: 'obj '{ 'form':'ID  ', 'want':'DTcn', 'seld':65536, 'from':'obj '{ 'form':'ID  ', 'want':'DTkb', 'seld':2, 'from':[0x0,73073 "DEVONthink Pro 

I can see in Hazels script preview that it opens the correct folder and as well that it puts a file that i have to choose manually, into the right group (Kreditkartenabrechnung). But it still shows the error message and I can’t store the script in Hazel.

Thanks for your guidance,
Robert

macOS 10.14.3 (Mojave)
DEVONthink Pro Office 2.11.2

*SOLVED
I did the following to solve it:

  1. in Mojave give Hazel full disk access https://www.noodlesoft.com/kb/giving-hazel-full-disk-access-on-mojave/
  2. you need to add ```

return true

Tja, and now I’m looking for a way to delete the credit card files, because Hazel copies and copies and copies the bills into DEVONthink… :unamused:

Anyone around with AppleScript knowledge, please :confused:

It’s unclear if this is a Hazel or AppleScript issue. I would disable the rule until that is determined.
There’s also no repeat loop in the script you posted, so it’s quite possible Hazel is just reprocessing the file in the folder.

Thank you Sir.

I recognized the loop, but obviously I can not judge if it is a Hazel or AppleScript issue.

Receiving files in a folder, “automatically” move them into a DEVONthink group doesn’t seem to be an unusual workflow in general.

How do you do this?

Hi All,

I came across this old thread and it contains exactly (or close to) what I want to do.

Now my applescript (or any script)) knowledge is non-existent and the only scripting I’ve managed to put together is from other people’s work on forums like this.

So I expect my issue I’m having (with this script) is rather fundamental. I receive the following error:

Can’t make POSIX path of XXX into type string.

Is this because I have spaces in the POSIX path? If so, how do I deal with this?

Thank you

Seb

Which script? There are numerous scripts listed and referred to in this thread?

Apologies, should have been more specific. The script I’m trying to work with is the one that you reference in the following post:

tell application "Finder"
	set _path to (the POSIX path of theFile as string)
	set {_name, _extension} to {name, name extension} of theFile
	
	-- optional: hide extension in Finder
	set extension hidden of theFile to true
	
	-- optional: remove extension for DEVONthink displays
	set _name to text 1 thru -((count _extension) + 2) of _name
	set _extension to "." & _extension
end tell

-- Launch DEVONthink if it isn't already open.
tell application "System Events"
	if not (exists process "DEVONthink Pro Office") then
		tell application id "com.devon-technologies.thinkpro2" to activate
	end if
end tell

-- Import the file.

tell application id "com.devon-technologies.thinkpro2"
	set theGroup to get record with uuid "<group uuid>"
	
	-- choose one option, Index or Import, comment out the other
	set theImport to import _path name _name to theGroup
	-- set theIndex to indicate _path to theGroup
end tell