Powershell to correctly create file paths on windows and unix

I want to create a line for the file path inside the powershell script. I want this to work in both windows and mac.

Currently, the code is tightly bound to windows similar to paths ("\" β†’ windows, "/" β†’ unix): $templatep="$CoreRoot\templates\$serviceName"

I changed this to: $templatep= Join-Path $CoreRoot "templates" $serviceName And it works on a Mac with Powershell 6.0. BUT this does not work on my Windows server with Powershell 4. I need to do something like this:

$templatep= Join-Path $CoreRoot -ChildPath "templates" | Join-Path -ChildPath $serviceName

Any idea why this only works in my mac? Is this a new feature in PowerShell 5 or 6? I do not like when you have to dial a few connections. Is there a better way to do this?

Thanks!

+2
windows unix powershell
source share
1 answer

First, a workaround using the .NET platform:

 [IO.Path]::Combine('a', 'b', 'c') 

This gives a/b/c on Unix and a\b\c on Windows and conveniently supports any number of path components.

Note:

  • This workaround is for file system paths only, while Join-Path is for working with any PowerShell provider paths.

  • Make sure that none of the components except the first starts with \ (Windows) or / (Unix), because any previous component is ignored; for example on Windows:
    [IO.Path]::Combine('\a', '\b', 'c') # -> '\b\c' - '\a' is ignored(!)
    Note that Join-Path does not exhibit this behavior; see this answer for me.

As an alternative for sequencing Join-Path calls with a pipeline, you can simply use (...) (subexpression):

 Join-Path a (Join-Path bc) # -> 'a\b\c' (on Windows) 

I have no explanation for the differences in behavior ; syntax displayed by Join-Path -? , the same on both platforms as Windows PowerShell v5.1.14393.693 and PowerShell Core v6.0.0-alpha.14 (random parameters omitted):

 Join-Path [-Path] <String[]> [-ChildPath] <String> ... 

Based on this syntax, a call to Join-Path abc should lead to a syntax error , which really happens on Windows ( A positional parameter cannot be found that accepts argument 'c' ), but not on Unix platforms. [one ]

However , of course, it would be convenient if Join-Path worked with an arbitrary number of path components , and the fact that it already works in PowerShell Core may indicate upcoming changes in Windows PowerShell too.

Please note that even if [-Path] <String[]> is an array parameter, its purpose is not to accept multiple child paths of a path for a single output path, but to allow the union of several pairs of parent-child pairs ; eg:.

 $ Join-Path a,bc # same as: Join-Path -Path a,b -ChildPath c a\c b\c 

Finally, even though it is probably not recommended, you can often get away with hardcoding / as a path separator on both platforms , since many Windows API functions, as well as native PowerShell cmdlets, are accepted \ and / interchangeably.
However, not all utilities can behave this way, so it is generally safer to use a separator suitable for the platform.

For example, it works fine on Windows:

 Get-Item c:/windows/system32 # same as: Get-Item c:\windows\system32 

[1] Strictly speaking, this is not about the platform, but the PowerShell version: Join-Path abc works in the multi-platform version of PowerShell Core even on Windows - unlike Windows Windows PowerShell (since version 5.1). However, PowerShell Core is typically used only on Unix platforms.

+3
source share

All Articles