[System.IO.Path]::Combine不将我的powershell变量作为参数



为什么函数[System.IO.Path]::Combine不接受我的第一个参数?

PS C:WINDOWSsystem32> $g_basePath
F:DevOneClickTools

PS C:WINDOWSsystem32> [Tests.Utils]::CUSTOMASSEMBLY_TEST
CustomLogic.dll

PS C:WINDOWSsystem32> [System.IO.Path]::Combine($g_basePath, "bindebug", [Tests.Utils]::CUSTOMASSEMBLY_TEST)
bindebugCustomLogic.dll

第三个命令显示只有第二个和第三个参数连接在一起,还是使用了一个空字符串作为$g_basePath。。?

补充Martin Brandl的有用答案:

具体地说,[System.IO.Path]::Combine应用的反直觉逻辑是:;如果path2path3也是绝对路径,则合并操作将丢弃所有先前合并的路径并重置为该绝对路径"(这也适用于其他方法重载)。

换句话说:指定的以(包括\)或<letter>:(驱动器规范)开头的最后一个路径参数会导致忽略所有以前的路径

PS> [IO.Path]::Combine('foo', 'bar', 'baz')
baz  # !! 'foo' and 'bar' were ignored

对于预期的行为——初始应被视为除第一个之外的每个路径组件的可选部分——确保除第一个之外的每个组件都不以开头——Join-Path按预期处理。

简单函数可以做到这一点:

# Combines array of path components $a to a single path.
function combine([string[]] $a) {
[IO.Path]::Combine([string[]] (@($a[0]) + $a[1..$($a.count-1)] -replace '^\', '')) 
}

请注意,转换为[string[]]对这一操作至关重要。

示例调用:

PS> combine 'foo', 'bar', 'baz'
foobarbaz  # as expected

使用Join-Path仅支持组件(自Windows PowerShell v5.1[1]起),使用管道链接多个调用的替代方法是(...)嵌套多个调用:

PS> Join-Path foo (Join-Path bar baz)
foobarbaz 

请注意,即使嵌套有些尴尬,也不需要担心以开头的从属组件。


至于PowerShell自己的Join-Pathcmdlet的逻辑:

虽然期望-ChildPath参数支持路径的数组是可以理解的(事实并非如此),但重要的是要理解Join-Path的设计与[System.IO.Path]::Combine()的设计有根本不同,因为Windows PowerShell v5.1[1]:

  • Join-Path使用多个输入路径来生成多个输出路径,而不是将输入路径解释为单个输出路径的组件。

  • 输入路径是父路径和子路径的,每对都被连接并产生自己的输出路径:

    • PS> Join-Path foo bar foobar
      • 缩写:Join-Path -Path foo -ChildPath bar
      • 请注意,与[System.IO.Path]::Combine()不同,PS是如何处理子路径中可选的前导
  • 虽然父路径参数(-Path)确实支持父路径的数组,但子路径参数(-ChildPath)不支持,尽管与-Resolve参数和通配符组合使用时,它可以有效地生成多个子路径。

    • PS> Join-Path -Path foo, baz -ChildPath bar foobar bazbar
    • 请注意2输出路径是如何通过将每个父路径和一个子路径配对生成的
  • [System.IO.Path]::Combine()不同,Join-Path可选地支持使用-Resolve:解析通配符路径

    • PS> Join-Path -Resolve C:Win* Sys* C:WindowsSystem C:WindowsSystem32 C:WindowsSystemApps C:WindowsSystemResources C:WindowsSysWOW64 C:Windowssystem.ini
  • 最后,值得注意的是,Join-Path不仅适用于文件系统路径,还适用于任何PowerShell[分层数据存储]提供程序的路径,并应用提供程序适当的路径分隔符。


[1]跨平台PowerShell版本,PowerShell核心,自v6.0.0起,已经支持任意数量的子组件启用Join-Path a b c等调用以生成abc(Windows)或a/b/c(Unix),而自v5.1起的Windows本机Windows PowerShell版本仍然不支持它。
此新行为尚未记录在案(甚至未在Join-Path -?中反映语法),但它最终可能会进入Windows PowerShell(从而进入所有版本)。

只需省略第二个路径上的前导反斜杠

[System.IO.Path]::Combine($g_basePath, "bindebug", [Tests.Utils]::CUSTOMASSEMBLY_TEST)

纯PowerShell尝试将使用Join-path cmdlet两次:

Join-Path $g_basePath  'bindebug' | Join-path -ChildPath [Tests.Utils]::CUSTOMASSEMBLY_TEST

最新更新