How Can I Invoke Shell Command `which`?

You don't need to echo, and using it can mask errors. Try just which runhaskell instead. You could also try

#!/bin/bash
which runhaskell

...because which is a bash built-in so you'll side-step any PATH problems (it's a separate utility in sh, KM's default shell).

And what do you get if you try it in Terminal?

Thank you for your reply !

The problem is KM doesn't have access to the paths I've added to the PATH variable and I would like to avoid adding an enviromental variable in KM.

Do you think that is possible ?

You can set PATH within your script just before invoking which. That way, which can do its job without affecting Keyboard Maestro globally.

1 Like

Thank you, @drdrang. Could you show me an example ?

It's the same as everywhere else in *nix: PATH=/path/to/add:$PATH

So if you had myUtil in /usr/local/oddpath your script would be

PATH=/usr/local/oddpath:$PATH
myUtil

Of course, you could just use an explicit path when you call myUtil:

/usr/local/oddpath/myUtil
1 Like

Any special reason you're echoing the result of a sub-shell, instead of using the bare command?

1 Like

Thank you @Nige_S. I wonder how I missed that.

Thank you for asking. I would like to create a script which runs Haskell code. The problem is, each user could have the path to runhaskell in a different location. So, using which (or another tool), I would like to get the exact location of the executable.

Comprende – but it's probably not necessary to echo the result:

For instance – this works for me:

"$(which bbedit)" ~/'Desktop/Test File.txt'

Yes, that would be ideal for me. However, I wouldn't know beforehand where is runhaskell executable. So, the script should locate the item, first.

Do you know if that is possible ?

Your executable script would have to be in the path somewhere to do something like this:

"$(which bbedit)" "$(which testexe)"

1 Like

Thank you, @ccstone.

Unfortunately, I won't know beforehand where the executable location is. So, I am wondering if there is some shell command that allows me to first find the executable path.

You could use locate to find all runhaskells, parse the results for binaries, guess at which to use if there's more than one... Yuck! Oh -- and, by default, locate's database hasn't been built so you'll have to get the user to do that first and wait (and wait, and wait...).

I can think of three ways round this problem. You also distribute the Haskell install, set to put the binary in a known, consistent, place. You tell users that they must install Haskell in a known, consistent, place. Or you have a Global__runhaskellPath in your macro, and on first run you pop a "Please select your Haskell install" dialog, grab the path from that, and use

PATH="$KMVAR_Global__runhaskellPath":$PATH

...at the top of your shell script. The global will persist, so they won't be asked again, but you should probably put some error checking there in case they move stuff around!

I'd try the latter, it seems "friendlier" to your users. It's totally untested, but you should be able to get it (or similar) to work.

2 Likes

I thought something along those lines :sweat_smile:.

Thank you for taking the time to give me options ! I'll ponder them.

Unless your users are on "managed" Macs (via an MDM such as Apple School Manager, Jamf, Munki, etc) I'd jump straight to option 3 and let them tell you where Haskell was installed -- a nicer experience for them and easier for you!

Searching a user's entire system for an executable or script seems very disorganized if not actually hacker'ish...

I'd prefer to require them to place the script in a certain location, and then I'd error-check and make them fix it if necessary.

If you really need to search then mdls is probably the way to go.

mdfind -onlyin / 'kMDItemFSName == "tellEddie"cd'

Otherwise I'd use find rather than locate, unless I knew for a fact that locate was indexed and up-to-date.

find / -iname "tellEddie"
/usr/local/bin/tellEddie
1 Like

I really appreciate your opinion. Thank you.

My runhaskell executable is in:

~/.ghcup/bin/runhaskell

However, the command doesn't find anything:

mdfind -onlyin / 'kMDItemFSName == "runhaskell"cd'

Is it correct ? Why do you append cd at the end ?

1 Like

I would like to share the plug-in here. It is already published. However, I would like to remove friction for the users.

Hmm... I can confirm that here.

Best guess is that Spotlight is not indexing the invisible folder.

Those are the case-insensitive and ignore diacriticals flags.

1 Like

This is a Keyboard Maestro plug-in?

Why not just embed the script in the plug-in?

Hence the "Yuck!" :wink:

Which means people will have to install Haskell, which (presumably, I've not done it) means they'll also have ~/.ghcup/bin/runhaskell. So I suggest you test for that, use it if it's there, and throw a "Please locate..." prompt if it isn't.

1 Like