Help needed: utilize a third-party command line utility in Smart Rules resulting in "command not found"

Hi all,

I’m building a Smart Rule that involves URL-encoding the titles of DT records. After searching for ways to perform URL encoding in AppleScript, I chose a npm package called url-decode-encode-cli. With the help of this utility, I successfully performed URL encode and decode when running commands in Terminal.app.

I then tried to use do shell script in the Execute Script action in the Smart Rule. Here’s a watered-down version of my script:

on performSmartRule(theRecords)
	tell application id "DNtp"
		repeat with theRecord in theRecords
			set encodedTitle to do shell script "echo 'test title' | url-encode"
			set the URL of theRecord to encodedTitle
		end repeat
	end tell
end performSmartRule

but DT log said sh: url-encode: command not found.

My questions is: Why can’t the AppleScript in the Smart Rule access the third-party command line utility I installed, and how can I enable access to it?

Thank you in advance :slight_smile:

Does it actually work in the Script Editor.app?

npm is the package manager of node.js

The error message is fairly clear: urlencode cannot be found. That message is not coming from DT but from the shell itself.

Do you see the exact same message if you run the command

"echo 'test title' | url-encode"

on the command line, i.e. in the Terminal? If you do, then you have to make sure that the shell can find the command. Read up on node.js, it’s installation location etc. Or, and probably a lot simpler, install a proper urlencoder that is independent of node.js.

If you do not see this error message, then you might want to find out where urlenode is installed:
which urlencode will tell you the complete path to the command (perhaps something like ~/.node/modules/urlencode). Copy and paste it into your AppleScript.

BTW: What’s the point in encoding the title of an arbitrary record to an URL-encoded string? I don’t find %20 easier to read then a simple space, but YMMV, of course.

No, url-encode-decode-cli works as expected when acceessed from Terminal.app.

I was aware that this utility depends on Node.js and I already installed it. I searched for a “proper urlencoder” but didn’t find a satisfatory one.

The shell can access the utility, but when I run the which commands, it too says it cannot be found. I have no idea what’s happening here:

Long story short, I’m trying to build a Smart Rule that automatically assemles the URL scheme of another app and populate the URL fields.

It’s a bit pointless to use which on something with a different name than the one one is looking for. I should have been more thorough when reading and replying:
which url-encode
should tell you the location of the command

Ah, thank you for your patience and help. I guess I really don’t know what I’m doing. :sweat_smile:

I ran the correct command and found its location at /usr/local/bin/url-encode, so in the script I replaced the echo 'test title' | url-encode" bit with echo 'test title' | /usr/local/bin/url-encode.

Now the new log error is env: node: No such file or directory. I guess that means the shell doesn’t know where Node.js is installed, right? But how do I specify its location, which is /usr/local/bin/node, in the Smart Rule AppleScript?

Again, thank you for patiently helping me,

I somehow missed your reply, sorry Christian.

I wanted to test the script in Script Editor.app as well, but since I was writing an Embedded AppleScript rather than an External one in the Execute Script Action, I have no idea how to run this script outside of DT. Copy-and-paste results in Script Editor.app returning nothing, and if I remove the first and last line, Script Editor.app couldn’t find the variable theRecord.

Risking to be impolite, I’m not going to contradict you here :wink:
Seriously, we can probably get this working somehow, but I’d suggest that you get a minimum of understanding in Shell programming etc.

Back to the question at hand: Now you know where url-encode is located. So which node might be in order, unless you’re sure that it is located in /usr/local/bin as well. Basically, you have to provide a PATH variable to the shell script you’re running that mimicks the PATH your login shell uses. If you’re still on bash, something like
"(export PATH=\"/usr/local/bin:$PATH\" && echo 'bla' | url-encode)"
might work (I just saw something like that on stackexchange). The same command might also work with zsh. In any case, it’s probably best to give it a try in the Terminal first.

All this makes it overly complicated, I think. There’s a pure shell version of url-encode on Github. Probably slow, though.
Then there’s a simple binary at Github

If you do not need a smart rule, a simple JavaScript script might do the trick:

(() => {
  let app = Application("DEVONthink 3");
  let records = app.selection();
  records.forEach(r => {
    let str = r.name(); /* or whatver attribute of the record you want to encode here */
    let urlEncoded = encodeURIComponent(str);
    r.url = urlEncoded;
  })
})()

But beware, this does probably not work as external script in a smart rule!

1 Like

I had a vague idea this had something to do with PATH, so I searched on StackOverflow and ran a export PATH=$PATH:/usr/local/git/bin command, which didn’t solve the issue at all.

I initially thought this would be a trivial task, but in hindsight I have clearly bitten off more than I can chew. :sweat_smile:

Thank you for providing many other solutions, I’ll see what I can do with these.

If the stuff is in /usr/local/bin, using /usr/local/git/bin doesn’t help. Also, the && and the parenthesis in the command are important so that the path gets propagated to the 2nd part of the pipe.

Oops, that was a silly typo, my bad.

I modified the Smart Rule according to this and now everything works as expected. Thank you for patiently helping me with an issue that’s actually not DT-related at all :sweat_smile: There’s so much that I need to learn!