Blog Post

PowerShell Split-Path Bug And A Workaround


Split-Path is a cmdlet built into Windows PowerShell that returns a specific part of a path, e.g.  a parent directory or a filename. Here's a simple example of how it works:

PS C:\Users\Kendal> $Path = Get-Location
PS C:\Users\Kendal> Split-Path $Path

But try it on a Path that doesn't exist on the machine running the command and you get an error:

PS C:\Users\Kendal> $Path = 'Q:\Users\Kendal\somefile.txt'
PS C:\Users\Kendal> Split-Path -Path $Path
Split-Path : Cannot find drive. A drive with the name 'Q' does not exist.
At line:1 char:11
+ Split-Path <<<<  -Path $Path
    + CategoryInfo          : ObjectNotFound: (Q:String) [Split-Path], DriveNotFoundException
    + FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.SplitPathCommand

One way you'd see this problem is using SMO to connect to a remote SQL Server and retrieve the paths of each database file, then try to use Split-Path to get the filenames or their parent paths. This Connect Bug indicates that the issue is fixed, but only in PowerShell V3; I can reproduce the error consistently in PowerShell V2.

The workaround is pretty simple: Use the static methods in the System.IO.Path .NET class to get the directory and file names. Using the same path in the previous example, here's how it looks:

PS C:\Users\Kendal> $Path = 'Q:\Users\Kendal\somefile.txt'
PS C:\Users\Kendal> [System.IO.Path]::GetDirectoryName($Path)
PS C:\Users\Kendal> [System.IO.Path]::GetFileName($Path)

A bonus is that using static .NET methods tend to be faster than their equivalent PowerShell cmdlet - in this example 3-4 times faster. With most scripts speed probably isn't as much of an issue as flexibility but if you're looking to eek out every bit of performance possible (and avoid this particular bug) using static .NET methods is the way to go.