Intro
For the past few months, I’ve been challenging myself a bit more when it comes to learning and improving my skills. During that journey, I stumbled upon a site called Boot.Dev.
What caught my attention is that it teaches backend development using a kind of Role Playing Game style. Through this platform, you can explore various backend topics, from languages like Python and Golang to tools like Git and SQL, all while progressing through quests and leveling up your skills.
Disclaimer: This post is not being sponsored by Boot.Dev!
One of the things I came across – and found quite interesting – was the use of recursive functions. Naturally, I was curious whether this concept could be applied in PowerShell as well. The answer is: yes.
In this post, I want to dive into what makes recursion so special, how it works, and when it can be useful in your scripts.
What are Recursive Functions?
Recursion could feel a bit like the movie Inception or a Matryoshka doll. It’s a tricky concept to grasp, but actually it’s not that hard. Don’t be intimidated by it. A recursive function is just a function that calls itself. I’ll show you in a bit an example of a recursive function in PowerShell.
When to use them?
We can iterate over a list by using a loop, but when we need to iterate Tree structures a loop isn’t the best way to solve the problem. The problem here lies with that we can’t predict the depth. For instance if we want to create our own custom function to map a directory and its contents. We can’t predict how many directory a directory has and how deep this goes. In this case we can create and use a recursive function.
Various math calculations also are prime candidates for recursion. for example Factorials (n!) or Fibonacci. While the recursive variants are quite a bit easier to read, there is a drawback. If the depth (or calculations) gets too big, an iterative solution is way more efficient. See our GitHub for some code examples.
Example
Let’s take the following case: We got a JSON file representing a file system structure. Our task is to create a function to transform this JSON file to filepaths (e.g. /dir1/dir2/filename.txt). The JSON has the following layout: A child directory’s value is a hashtable and a file’s value is $null.
Function:
function List-Files {
param (
[hashtable]$ParentDirectory,
[string]$CurrentFilePath = ""
)
$FileList = @()
foreach ($key in $ParentDirectory.Keys) {
$NewFilePath = "$CurrentFilePath/$key"
$val = $ParentDirectory[$key]
if ($null -eq $val) {
$FileList += $NewFilePath
}
else {
$FileList += List-Files -ParentDirectory $val -CurrentFilePath $NewFilePath
}
}
return $FileList
}
JSON\Code:
$json = '{
"Documents": {
"Proposal.docx": null,
"Report": {
"AnnualReport.pdf": null,
"Financials.xlsx": null
}
},
"Downloads": {
"Reports_Last_3_Years.zip": null,
"picture1.jpg": null,
"Reports_Last_3_Years": {
"2024": {
"AnnualReport.pdf": null,
"Financials.xlsx": null
},
"2023": {
"Boring.pdf": null,
"Moneys.xlsx": null
},
"2022": {
"Report.docx": null,
"disclaimer.txt": null,
"export.sql": null
}
}
}
}'
$Directory = $json | ConvertFrom-Json -AsHashtable
$List = List-Files -ParentDirectory $Directory -CurrentFilePath "C:/Users/Me"
$List | ForEach-Object { Write-Output $_ }
Output:
C:/Users/Me/Documents/Proposal.docx
C:/Users/Me/Documents/Report/AnnualReport.pdf
C:/Users/Me/Documents/Report/Financials.xlsx
C:/Users/Me/Downloads/Reports_Last_3_Years.zip
C:/Users/Me/Downloads/picture1.jpg
C:/Users/Me/Downloads/Reports_Last_3_Years/2024/AnnualReport.pdf
C:/Users/Me/Downloads/Reports_Last_3_Years/2024/Financials.xlsx
C:/Users/Me/Downloads/Reports_Last_3_Years/2023/Boring.pdf
C:/Users/Me/Downloads/Reports_Last_3_Years/2023/Moneys.xlsx
C:/Users/Me/Downloads/Reports_Last_3_Years/2022/Report.docx
C:/Users/Me/Downloads/Reports_Last_3_Years/2022/disclaimer.txt
C:/Users/Me/Downloads/Reports_Last_3_Years/2022/export.sql
Breakdown
Because a JSON representation isn’t easy to iterate on its own, we transform it into a hashtable. Then we create a function that can recursively make its way through the hashtable and build the requested file paths.
For the parameters we choose the following:
$ParentDirectory
: A hashtable representing the current level of the directory structure.$CurrentFilePath
: A string that keeps track of the path built so far.
Then we initialize by using an empty array $FileList
to store the resulting file paths.
For each key, a new path is constructed by appending the key to the current path. If the value associated with the key is $null
, it’s treated as a file. The constructed path is added to the list.
If the value is another hashtable, it’s treated as a folder. The function calls itself recursively, passing the sub-hashtable and the updated path.
Once all keys are processed, the function returns the complete list of file paths.
Recap
I hope you enjoyed exploring recursive functions in PowerShell with me. There’s still a lot we didn’t touch on, but part of the fun is exploring the rest on your own, right?
If you have any questions, or if I made a mistake in my explanation, please let me know. I’m always eager to learn too.
And if Boot.Dev sparked your interest and you’d like to join, feel free to use this referral link and/or this referral link. That way, we both get some nice goodies in the “game”, if you reach level 20.
Leave a Reply