Hmmm. Briefly, recursion is typically less work work for the programmer (once you wrap your head around it) but conversley more work for the computer, especially the stack that must hold interim results. Also typically, a well written iterative function will run faster than a recursive one, but it will require more coding.
However, some problems lend themselves to recursion better than iterative solutions, like anything that can be nested -- directory structures, blocks, lists etc.
Here's a quick variant that attempts to optimize and illuminate the recursion process a bit by formally declaring local defuns where lambda calls would typically be invoked --
(defun GetFolders ( path / _GetFolders _Collector _Main )
(defun _GetFolders ( path / folders )
(defun _GetFolders ( path )
(cddr
(vl-directory-files path nil -1)
)
)
(if (vl-position "."
(setq folders
(vl-directory-files path nil -1)
)
)
(cddr folders)
folders
)
)
(defun _Collector ( folder / temp )
(cons
(setq temp (strcat path "\\" folder))
(apply 'append (_Main temp))
)
)
(defun _Main ( path )
(mapcar '_Collector
(_GetFolders path)
)
)
(apply 'append (_Main path))
)
While it looks verbose it should perform decent enough and is safer than some of the variants already posted (not dissing, just an observation). See the "An aside ..." comment at the end of this post.
If run on a folder structure like this --
C:\Folder1
|
+-- Folder1
| |
| +-- Folder1
| |
| +-- Folder2
| |
| +-- Folder3
|
+-- Folder2
| |
| +-- Folder1
| |
| +-- Folder2
| |
| +-- Folder3
|
+-- Folder3
|
+-- Folder1
|
+-- Folder2
|
+-- Folder3
it will return a list of 12 items.
(GetFolders "C:\\Folder1")
( "c:\\folder1\\folder1"
"c:\\folder1\\folder1\\folder1"
"c:\\folder1\\folder1\\folder2"
"c:\\folder1\\folder1\\folder3"
"c:\\folder1\\folder2"
"c:\\folder1\\folder2\\folder1"
"c:\\folder1\\folder2\\folder2"
"c:\\folder1\\folder2\\folder3"
"c:\\folder1\\folder3"
"c:\\folder1\\folder3\\folder1"
"c:\\folder1\\folder3\\folder2"
"c:\\folder1\\folder3\\folder3"
)
An aside ... using cddr to strip out "." and ".." unconditionally is a little dangerous, as the vl-directory-files function will not include them if you run said function on a root directory like (vl-directory-files "c:\\" nil -1). That's why I redefine the _GetFolders function after the first call. On the first call it checks to see if "." is a member of the result list and if so strips it (and ".." ) out. Thereafter the program uses the redefined version which uses cddr unconditionally, as there is no need to pay the penaly of testing each subsequent iteration.
Hope (that makes sense and) that helps some.