To emulate Join-Path
's behavior without the - surprising and vexing - requirement that a drive spec. (e.g., N:
) refer to an existing drive (even though no other components are required to exist):
Pragmatically speaking, you can simply use string concatenation / interpolation to join your path components:
$dir = 'N:\foo'; $file = 'bar'
# String concatenation
$joinedPath = $dir + '\' + $file
# String interpolation
$joinedPath = "$dir\$file"
# With an open-ended number of path components.
$components = $dir, 'sub', $file
$joinedPath = $components -join '\'
While, depending on the input components, this can result in accidentally duplicated path separators (e.g., N:\foo\\bar
), this is usually not a problem, because the file-system APIs treat such duplicates as a single separator; that is, N:\foo\\bar
is treated the same as N:\foo\bar
.
If you want to avoid duplicated separators, see the solution in the next section.
To more fully emulate Join-Path
, which involves removing accidentally duplicated separators and normalizing them to the platform-native form (e.g., on Windows, /
-> \
), use the following:
$dir = 'N:\foo'; $file = 'bar.txt'
$components = $dir, $file
$joinedPath =
($components -join '\') -replace '(?!^)([\\/])+', [IO.Path]::DirectorySeparatorChar
To wrap this up in a (very simple) function, join-AnyPath
:
function join-AnyPath {
($args -join '\') -replace '(?!^)([\\/])+', [IO.Path]::DirectorySeparatorChar
}
# Sample call
join-AnyPath N:\dir\ /foo/ bar.txt
The above yields N:\dir\foo\bar.txt
(on Windows).
Note: Theo points out that there's also the [IO.Path]::Combine()
.NET method, but while it doesn't require that a drive exist either, its behavior differs from Join-Path
with respect to how \
-prefixed components are handled, which can lead to surprising results: see this answer.