How To Use KM Variables in Shell Script to Get List of Files in All SubFolders?

###How To Use KM Variables in Shell Script to Get List of Files in All SubFolders?

Help please. I've tried various syntax, and studied the post in this ref, but I can't make the last Action below work. What am I doing wrong?

I am trying to run a mdfind like this:

mdfind -onlyin "$KMVAR_Folder_To_Search" 'kMDItemFSName == "*.$KMVAR_Ext_To_Search"c'

where I want to use KM vars for the folder to be searched, and for the file extension.

This works when I use the data explicitly:

mdfind -onlyin ~/Documents/Test/ 'kMDItemFSName == "*.txt"c'

MACRO: Get List of Files in All SubFolders [FILES]

Get List of Files in All SubFolders [FILES].kmmacros (5.5 KB)

In the shell, variables are only interpolated within double quotes, not within single quotes.

echo $A "$A" '$A'

Note even the styling of the quoting shows the difference.

The output is:

5 5 $A

Hence the second KMVAR is not interpolated but used verbatim as $KMVAR_etc in the search.

And easy way to debug this is to change "mdfind" to "echo" and you can see exactly what the mdfind sees as parameters.

Thanks Peter.

So how do I get the value of the KM var inside of single quotes?

With double quotes maybe?:

mdfind -onlyin "$KMVAR_Folder_To_Search" "kMDItemFSName == \"*.$KMVAR_Ext_To_Search\"c"

Thanks, Tom.
Unfortunately, it’s still not quite right. mdfind requires single quotes around the kMDItemFSName phrase, as in:

mdfind -onlyin ~/Documents/Test/ 'kMDItemFSName == "*.txt"c'

When I try your code I get nothing output, not even a blank window.

When I try this:

echo $KMVAR_Folder_To_Search
echo $KMVAR_Ext_To_Search

echo -onlyin "$KMVAR_Folder_To_Search" "kMDItemFSName == \"*.$KMVAR_Ext_To_Search\"c"
mdfind -onlyin "$KMVAR_Folder_To_Search" "kMDItemFSName == \"*.$KMVAR_Ext_To_Search\"c"

I get this

-onlyin ~/Documents/Test/ kMDItemFSName == "*.txt"c

NOTE there is NO output from the mdfind command.

Any other ideas?

This is very frustrating.

I tried this, which does NOT work:

Set variable kMDItem to
'kMDItemFSName == "*.%Variable%Ext_To_Search%"c'


echo $KMVAR_Folder_To_Search
echo $KMVAR_kMDItem

echo -onlyin "$KMVAR_Folder_To_Search" $KMVAR_kMDItem
mdfind -onlyin "$KMVAR_Folder_To_Search" $KMVAR_kMDItem

returns this:

'kMDItemFSName == "*.txt"c'
-onlyin ~/Documents/Test/ 'kMDItemFSName == "*.txt"c'
Failed to create query for ''kMDItemFSName == "*.txt"c''.


I even copied the echo output into a new Execute Shell, and it worked fine:

mdfind -onlyin ~/Documents/Test/ 'kMDItemFSName == "*.txt"c'

Hey JM,

Quoting in the shell gets rather complicated especially when you have embedded quotes within quotes.

Keep in mind that single quotes are literal, but double-quotes allow shell-expansion to take place.

Here's what I had to do to make this little adventure work neatly (see macro below).

Note the difference between this read command and the previous one you've seen.

It uses a shell function called a here-document.

(The text after << is an arbitrary word that makes sense to the user and the context.)

<<'EOF' is what you saw before, and it causes the read text to be completely literal (notice the single quotes).

In this macro I've used <<EOT with no quotes, and that lets variable expansion take place in the here-document.

This makes composing the command relatively easy.

I had to resort to eval to get it to run correctly though.


REFERENCE: Using variables inside a bash heredoc

mdfind with Variables.kmmacros (2.8 KB)

1 Like

BINGO! You did it! :+1:

Thanks Chris. I would never have figured that out.

May I suggest that you post your macro in the Forum Macro section.
I’ll then add a reference to it in the KM Wiki Shell Scripting article.

Many thanks, @ccstone, for posting the idea with the Here doc in this context! I only ever made use of this for executing multiline AppleScripts in the shell (with osascript <<-[…]) but I never was really aware of the quotes and expanding behavior. This will prove useful for many otherwise ugly cases with problematic quote nesting or variable expansion!:beers:

@JMichaelTX, for the double quote approach I’ve posted yesterday I only had tested an abstracted equivalent in a BBEdit shell worksheet, which —to my surprise— did work. But, honestly, I wasn’t sure if it will work in the KM environment too.

But now when I’m trying it in ccstone’s macro it does work as well. (Or better said: it produces exactly the same output as the Here doc version.)

So it isn’t quite clear to me, why it does work here but not for you. Could you try this:

mdfind with Variables (double quotes).kmmacros (3.4 KB)

Of course the Here doc approach is the best solution, and I don’t know wether the use of double quotes in the mdfind command has any side effects, but I’m just curious to learn what is going on, and why it works, where it shouldn’t (as you correctly pointed out mdfind normally wants single quotes).

@Tom, I just tried your macro and it worked this time.
I have no idea why your double quotes did not work before.

Double quotes with back-slashed quotes (like @Tom showed) are the way to go for this.

Quoting is always an issue, and the more layers, the more problems as each layer unravels one level of quoting.

In this case you have BBEdit’s shell worksheet and/or Keyboard Maestro’s action, followed by the bash sell, followed by the mdfind application itself doing quoting.

It is never going to be particularly easy to make that work.