Behind the PowerShell Pipeline logo

Behind the PowerShell Pipeline

Archives
Log in
Subscribe
July 14, 2026

Don't Miss Out

In this issue:

  • Joining Paths
  • Using a StopWatch
  • A Real World Implementation
    • Project-Report.ps1
  • Summary

We have been exploring hidden, or at least often overlooked, PowerShell features and commands. It is always a challenge to resolve "You don't know what you don't know". This is why the PowerShell community is awesome and I encourage you to attend user group meetings and the PowerShell Summit. The community loves to share what they know, as do I, which is why we're here. Let's get to it.

Joining Paths

I have always been a big proponent of the Join-Path cmdlet. I don't think you should be building paths like this:

$file = "C:\work\" + "demo.ps1"

It is very easy to forget the slash. This also isn't a good technique to ensure your code will run cross-platform. This is why Join-Path is the better choice.

PS C:\> $file = Join-Path -Path $Home -ChildPath demo.ps1
PS C:\> Write-Host "Creating script file $file"
Creating script file C:\Users\jeff\demo.ps1

The same code works cross-platform.

PS /home/jeff> $file = Join-Path -Path $Home -ChildPath demo.ps1
PS /home/jeff> Write-Host "Creating script file $file"
Creating script file /home/jeff/demo.ps1

Where things can get tricky is when you have a deeper path to create.

PS C:\> Join-Path -Path ([IO.Path]::GetTempPath()) -ChildPath foo\bar\log.txt
C:\Users\jeff\AppData\Local\Temp\foo\bar\log.txt

Making sure you have the right slashes can be a nuisance. PowerShell 7 includes a new parameter that simplifies the process.

PS C:\> Join-Path -Path ([IO.Path]::GetTempPath()) -ChildPath foo -AdditionalChildPath foo,log.txt 
C:\Users\jeff\AppData\Local\Temp\foo\foo\log.txt

If you aren't in the habit of reading help, you may not know about AdditionalChildPath. Enter an array of paths to join, in order, and PowerShell does the rest. This is very handy when writing code that will run cross-platform.

PS /home/jeff> Join-Path -Path ([IO.Path]::GetTempPath()) -ChildPath foo -AdditionalChildPath foo,log.txt
/tmp/foo/foo/log.txt

I should point out that you can also pass an array of strings to ChildPath.

PS C:\> Join-Path -path c:\scripts -ChildPath foo,bar,jeff 
c:\scripts\foo\bar\jeff

The help documentation suggests that this won't work. I can verify this with Get-ParameterInfo from the PSScriptTools module.

PS C:\> Get-ParameterInfo Join-Path

   ParameterSet: __AllParameterSets

Name            Aliases         Mandatory    Position    Type
----            -------         ---------    --------    ----
Path            PSPath          True         0           System.String[]
ChildPath                       True         1           System.String[]
AdditionalChil…             False        2           System.String[]
Credential                      False        Named       System.Management.Automation.PSCredential
Resolve                         False        Named       System.Management.Automation.SwitchParam...

Whether you use ChildPath or AdditionalChildPaths is up to you and might depend on the context. However, ChildPath is required if you want to use AdditionalChildPaths.

There is no reason to use concatenation to create paths when there is a cmdlet that will simplify the process.

Want to read the full issue?
Already a paid subscriber? Click here to log in.
GitHub
Bluesky
LinkedIn
Mastodon
jdhitsolutions.github.io
Powered by Buttondown, the easiest way to start and grow your newsletter.