简体   繁体   中英

Powershell to generate file paths correctly in windows and unix

I want to generate a string for a file path inside a powershell script. I want this to work in both in windows and mac.

At the moment the code is hardcoded to windows like paths ("\\" -> windows, "/" -> unix): $templatep="$CoreRoot\\templates\\$serviceName"

I changed this to: $templatep= Join-Path $CoreRoot "templates" $serviceName And it works in mac with Powershell 6.0. BUT it doesn't work in my windows server with Powershell 4. I have to do something like this:

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

Any idea why this is just working in my mac? Is this a new feature in powershell 5 or 6? I dont't like the having to pipe multiple Join-Paths. Is there a better way to do this?

Thanks!

First, a workaround using the .NET framework:

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

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

Note:

  • This workaround is only for filesystem paths, whereas Join-Path is designed to work with any PowerShell drive provider's paths.

  • Make sure that no component other than the first starts with \\ (Windows) or / (Unix), because any preceding component is then ignored; eg, 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 details.

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

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

The syntax displayed by Join-Path -? as of Windows PowerShell v5.1.14393.693 (incidental parameters omitted):

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

This syntax implies that invocation Join-Path abc results in a syntax error in Windows PowerShell , because there is no parameter to bind the c argument to.

By contrast, the syntax displayed in PowerShell (Core) v6+ reveals an additional parameter:

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

It is the additional -AdditionalChildPath parameter , which is declared in a manner that collects all remaining positional arguments that ( ValueFromRemainingArguments ), that makes specifying an arbitrary number of child components work , so that Join-Path abc indeed works, for instance.

Unfortunately, this enhancement won't be back-ported to Windows PowerShell.

Note that even though [-Path] <String[]> is an array parameter, its purpose is not to accept multiple child path components of a single output path, but to allow joining of multiple parent-child path pairs; eg:

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

Finally, even you can typically get away with hard-coding / as the path separator on both platforms , because many Windows API functions as well as PowerShell's own cmdlets accept \\ and / interchangeably .
However, not all utilities may behave this way, so it's generally safer to use the platform-appropriate separator.

For instance, the following works just fine on Windows:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM