Frequently, your code needs to ensure that certain prerequisites exist. For example, if you plan to download files to a local folder, you want to make sure this folder exists, and if it is still missing, create it.
This of course is not a problem, so you often encounter code like this:
# path to download files to:
$OutPath = "$env:temp\SampleData"
# does it already exist?
$exists = Test-Path -Path $OutPath -PathType Container
# no, create it:
if (!$exists)
{
$null = New-Item -Path $OutPath -ItemType Directory
}
There are two issues with this approach, though:
- Reusability: Since this task is a routine task that you’ll often need, you’ll find yourself repeating to code this test over and over again. Of course you could copy & paste the code snippet but would still have to adjust variable names.
- Clean Code: With each routine test, your code grows and becomes increasingly harder to read. Wouldn’t it be much better to exclude standard code that you know is ok, and focus entirely on the specific code that is really new?
Here is an alternative that is so much easier to read and use:
($OutPath = "$env:temp\SampleData") | Assert-FolderExists
Reusing Assertions
Assertions are just a special breed of PowerShell functions: Assert-FolderExists
takes any number of paths and makes sure the folders exist. If not, they are created. Clean, simple and reusable.
Placing a variable assignment in parenthesis is key for this: when an assignment is placed in parenthesis, the value is assigned to the variable and the value is also emitted, so a down-stream command can pick it up. Compare these two lines:
# simple assignment: $Path1 = "$env:windir\explorer.exe" # assignment PLUS output: ($Path2 = "$env:windir\explorer.exe")
The first line silently assigns the value. The second line also emits the assignment:
C:\Windows\explorer.exe
Filters Are Perfect Assertions
Filters are perfectly suited for assertions because with very little code, you get a fast pipeline-aware function that processes one or many input values. Assert-FolderExists
can be implemented like this:
filter Assert-FolderExists
{
$exists = Test-Path -Path $_ -PathType Container
if (!$exists) {
Write-Warning "$_ did not exist. Folder created."
$null = New-Item -Path $_ -ItemType Directory
}
}
Now it’s trivial to create one or more folders: simply pipe the paths to Assert-FolderExists
. You can pipe strings directly or use the parenthesis trick to take them from assignments:
# making sure a bunch of folders exist:
'C:\test1', 'C:\test2' | Assert-FolderExists
# making sure the path assigned to a variable exists:
($Path = 'c:\test3') | Assert-FolderExists
Using Functions
Filters are great when you want to exclusively process pipeline input. If you’d rather use named parameters, use pipeline-aware functions instead:
function Assert-FolderExists
{
param
(
[Parameter(Mandatory,ValueFromPipeline)]
[string[]]
$Path
)
process
{
foreach($_ in $Path)
{
$exists = Test-Path -Path $_ -PathType Container
if (!$exists) {
Write-Warning "$_ did not exist. Folder created."
$null = New-Item -Path $_ -ItemType Directory
}
}
}
}
Now you can use Assert-FolderExists
both via pipeline and via parameters:
# making sure the path assigned to a variable exists:
($Path = 'c:\test3') | Assert-FolderExists
# making sure a bunch of paths exist:
Assert-FolderExists -Path 'c:\test4', 'c:\test5'
Adding Assertions To Modules
Assert-FolderExists
is just an example of a frequently used assertions. Whenever you come across tests that are likely to be needed routinely, you may want to create an assertion function for it.
Since assertions are likely to be reused often, you should add them to your own PowerShell module so they are always available and do not bloat your script code. As an example, I have added the function Assert-PsOneFolderExists
to the module PSOneTools that you can download and install from the PowerShell Gallery:
Install-Module -Name PSOneTools -Scope CurrentUser -MinimumVersion 2.4 -Force
Once done, you can use Assert-PsOneFolderExists
(and many more useful PowerShell functions) in your script:
($test = 'c:\myFolder') | Assert-PsOneFolderExists