[SOLVED] Create list with all folders and sub folders (including sub sub folders, etc)

A while ago, @noisneil shared a macro to find Logic Patches and using an altered version of his macro I was able to find all .md files inside Obsidian by using this shell script:

find  "$KMVAR_Local__FolderPath" -maxdepth 99 -name "*.md" -exec basename {} .md  \;

How would I be able to change this to find folders, instead of files?

EDIT: I think I found it. Can someone confirm this is the right way to do it?

find  "$KMVAR_Local__FolderPath" -type d;

This seems to be working, but when I use it with the Prompt With List action, I see the full path and I just wanted it to show the folder's name. I tried different option inside the Filter action, but can't seem to find a solution

I guess I got it:

Search all folders inside Obsidian vault.kmmacros (24 KB)

Keyboard Maestro Export

I would have helped sooner if I wasn't on the phone.

My solution would have been different. I would have simply added a few words after the find command to strip out the unwanted information.

I think this would work, right on the find statement: (replace the dot with your KM variable)

find . -type d | rev | cut -f1 -d "/" | rev

Consider it a challenge to figure out how that works. I used a trick or two there.

1 Like

Feel free to share that. Always good to learn something new and to make macros as short as possible :wink:
I just found this script somewhere and since I'm not familiar with it, that's all I could do with it.

Yeah, that's too complex for my level (or lack thereof) of shell script knowledge...
Somewhere in there is probably something that says "cut everything all the way up to the last / but I wouldn't be able to understand it at all...

Ok I think I'm getting there from doing some research...
You reverse the whole path, then you cut one of the "columns" (the f1) then reverse it again, etc...
But can't really see how you achieve it. I would need a few more minutes

It's not that bad. You wanted just the basename. So the first thing I did was reverse ("rev") the contents of every line. :scream: Then I removed (with "cut") every "field" past the first "/" (since the lines are reversed, that means remove everything up to the last "/" inclusive), then I reversed the lines again ("rev") and like magic you get the basename of each path.

1 Like

Ok so it's what I was saying on my previous post :wink:
A few more minutes looking at it and I would be able to figure it out.
I was looking at this:

and this:

You solved the problem on your own! That's all that matters.

There are some contests online to see who can find the "shortest" script answer to a problem. I would never win those.

1 Like

Yeah, as long as it works... (even though, technically, I had some help from Neil and his macro).

But it's still good to learn other approaches and if I can remove a few actions from my macros by using your solution, that's always a plus.
Thanks for that!

That sounds like a good way to exercise the brain.

I think they call themselves "exercists."

1 Like

For sure! :wink:


Today I was working on this macro again, trying to finish it, and I noticed that your solution (for this particular macro) won't work, because I actually need the path itself.
I will keep your solution on my notes anyway, in case I need the name (which I'm sure I will).

Now I need to go back to the simple form:
find "$KMVAR_Local__FolderPath" -type d

but I would like to exclude 2 folders:
/Users/dannywyatt/Library/Mobile Documents/iCloud~md~obsidian/Documents/Danny Wyatt/.obsidian
/Users/dannywyatt/Library/Mobile Documents/iCloud~md~obsidian/Documents/Danny Wyatt/.trash

I was reading the topic below, but can't really understand how to achieve this

When I try this, it actually just shows me the .obsidian path, instead of excluding it:
find "$KMVAR_Local__FolderPath" -path "/Users/dannywyatt/Library/Mobile Documents/iCloud~md~obsidian/Documents/Danny Wyatt/.obsidian" -prune

It seems macOS is different about the syntax. It took a bit of experimentation, but I think this would work:

find "$KMVAR_Local__FolderPath" -type d  -name ".obsidian" \
-prune -or -type d -name ".trash" -prune -or -type d

Basically you have to use a -name flag before each thing to exclude, you have to list only the folder name within the top-level folder that you're searching (....Documents/DannyWyatt in this case), and (this is what was tripping me up), you have to add and -or -type d after each prune, or find will simply stop searching.

Please test and let me know if it works for you; it seems to work here in my testing. (You can remove the \ + line break from the above; I added that just to prevent one wide line in the post, though it should work as shown, too.)