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

时间:2016-06-12 17:52:51

标签: powershell

为什么函数[System.IO.Path]::Combine没有采用我的第一个参数?

PS C:\WINDOWS\system32> $g_basePath
F:\Dev\OneClickTools



PS C:\WINDOWS\system32> [Tests.Utils]::CUSTOMASSEMBLY_TEST
CustomLogic.dll



PS C:\WINDOWS\system32> [System.IO.Path]::Combine($g_basePath, "\bin\debug", [Tests.Utils]::CUSTOMASSEMBLY_TEST)
\bin\debug\CustomLogic.dll

第三个命令显示只连接了第二个和第三个参数,或者它是否使用空字符串$g_basePath ..?

2 个答案:

答案 0 :(得分:8)

只需省略第二条路径上的反斜杠

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

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

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

答案 1 :(得分:8)

补充Martin Brandl's helpful answer

具体来说, - 反直觉 - logic applied by [System.IO.Path]::Combine是:"如果 path2 path3 也是绝对路径,则合并操作会丢弃所有先前组合的路径并重置到该绝对路径。" (这类似于其他方法也适用于重载)。

换句话说:指定的 last 路径参数以\(包括\\)或<letter>:(驱动器规格)开头。导致所有先前路径被忽略

> [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[]]对于此工作至关重要。

示例电话:

> combine '\foo', '\bar', '\baz'
\foo\bar\baz  # as expected

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

> Join-Path \foo (Join-Path \bar \baz)
\foo\bar\baz 

请注意,即使嵌套有点笨拙,您也不必担心以\开头的从属组件。

至于PowerShell自己的Join-Path cmdlet 的逻辑:

虽然期望-ChildPath参数支持路径的数组是可以理解的,但它并不重要,理解这一点非常重要 Join-Path的设计与[System.IO.Path]::Combine() 的设计基本不同,自Windows PowerShell v5.1 [1] 起 :

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

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

    • > Join-Path \foo \bar \foo\bar
      • 简称:Join-Path -Path \foo -ChildPath \bar
      • 请注意PS与[System.IO.Path]::Combine()不同,如您所期望的那样处理子路径中的可选前导\
  • 虽然父路径参数(-Path 支持父路径的数组,但子路径参数({{1 ,但是当与-ChildPath参数和通配符结合使用时,它可以有效地生成多个子路径。

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

    • -Resolve
  • 最后值得注意的是> Join-Path -Resolve C:\Win* Sys* C:\Windows\System C:\Windows\System32 C:\Windows\SystemApps C:\Windows\SystemResources C:\Windows\SysWOW64 C:\Windows\system.ini不仅适用于文件系统路径,而且适用于任何PowerShell [分层数据存储]提供程序的路径,应用提供者适当的路径分隔符。 / p>

[1] 跨平台 PowerShell版本 PowerShell核心 ,自v6.0.0起, 支持任意数量的子组件enabling calls such as Join-Path a b c to yield a\b\c (Windows) or a/b/c (Unix),而从v5.1开始的Windows原生 Windows PowerShell 版本仍然不支持它。
这个新行为尚未记录(甚至没有在Join-Path中反映语法],但最终可能会进入Windows PowerShell(从而所有版本)。