2016-06-12 64 views
7

爲什麼不是功能[System.IO.Path]::Combine採取我的第一個參數?[System.IO.Path] ::結合沒有把我的PowerShell變量作爲參數?

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它..?

回答

7

只是忽略前導反斜槓你的第二路:

[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

啊謝謝......我以爲這種情報是建立在'[System.IO.Path] :: Combine'功能 – ibiza

+0

是的,我也這麼想過,只是試了一下;-)。 –

+2

謝謝,我想過使用Join-Path ...但是不得不使用Join-Path兩次有點難過:p – ibiza

8

爲了補充Martin Brandl's helpful answer

Spe實際上,反直覺 - logic applied by [System.IO.Path]::Combine是:「如果路徑2路徑3也是絕對路徑,則組合操作會丟棄所有先前組合的路徑並重置爲該絕對路徑。」 (這也適用於其他方法的重載)。

換句話說:最後路徑參數指定的開始與\(包括\\)或<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小命令的邏輯:

儘管這是可以理解到期望-ChildPath參數以支持的路徑的陣列(它不),這是重要了解Join-Path的設計根本不同於[System.IO.Path]::Combine(),從Windows PowerShell v5.1開始[1]

  • Join-Path使用多個輸入路徑,以產生多個輸出路徑而不是解釋輸入路徑作爲單個輸出路徑的部件。

  • 輸入路徑對(一個或多個)的父和子路徑,每對得到接合,並導致其自身的輸出路徑:

    • > Join-Path \foo \bar \foo\bar
      • 短爲: Join-Path -Path \foo -ChildPath \bar
      • 請注意PS與[System.IO.Path]::Combine()不同,它處理孩子的可選前導\如你所期望的那樣。
  • 而父路徑參數(-Path確實支持一個陣列的父路徑,子路徑參數(-ChildPath)不,雖然當與-Resolve組合參數和通配符,它​​可以有效地導致多個子路徑。

    • > 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
  • 最後,值得注意的是,Join-Path不是隻適用於文件系統路徑,但任何PowerShell [分層數據存儲]提供者的路徑,應用提供適當的路徑分隔符。


[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),而Windows自帶的Windows PowerShell版本至v5.1仍不支持rt it。
這種新行爲尚未記錄(甚至在Join-Path -?中甚至沒有反映語法),但它最終可能會進入Windows PowerShell(因此可能會進入所有版本)。

+1

這應該是被接受的答案。 –

相關問題