2016-06-12 16 views
7

Perché la funzione [System.IO.Path]::Combine non utilizza il mio primo parametro?[System.IO.Path] :: Combina non prendendo la mia variabile PowerShell come parametro?

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 

Il terzo comando mostra che solo il secondo e il terzo parametro sono concatenati o sta utilizzando una stringa vuota come $g_basePath ..?

risposta

7

Proprio omettere il backslash sul secondo percorso:

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

Un tentativo di PowerShell puro sarebbe quella di utilizzare il Join-path cmdlet due volte:

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

ah grazie ... Ho pensato che questa sorta di intelligenza fosse costruita nella funzione '[System.IO.Path] :: Combine ' – ibiza

+0

Sì, ho pensato anche io, ho appena provato ;-). –

+2

grazie, ho pensato di usare Join-Path ... ma dovrei usare Join-Path per due volte è un po 'triste: p – ibiza

8

Per completare Martin Brandl's helpful answer:

Spe in particolare, il - contro-intuitivo - logic applied by [System.IO.Path]::Combine è: "Se percorso2 o percorso3 è anche un percorso assoluto, l'operazione di combinazione elimina tutti i percorsi precedentemente combinati e si reimposta su quel percorso assoluto." (questo vale analogamente anche per gli altri metodi).

In altre parole: l'argomento percorso ultimo specificato che inizia con \ (compresi \\) o <letter>: provoca tutti i percorsi precedenti essere ignorato (una specifica unità.).

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

Per il comportamento visto - dove una prima \ dovrebbero essere trattati come un componente opzionale di ogni componente del percorso diverso dal primo - garantire che ogni componente, ma il primo non fa inizio con \ - Join-Path gestisce come ci si aspetterebbe.

Un semplice funzione possono farlo:

# 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 '^\\', '')) 
} 

Si noti che la fusione a [string[]] è fondamentale per far funzionare tutto questo.

chiamata Esempio:

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

Uso Join-Path, che supporta solo coppie di componenti come Windows PowerShell v5.1 [1] , alternativa all'utilizzo una pipeline per concatenare più chiamate è quella di nidificare con più chiamate con (...) :

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

Nota che, anche se la nidificazione è un po 'imbarazzante, NON è necessario preoccuparsi di componenti subordinate che iniziano con \.


quanto riguarda la logica del proprio Join-Path cmdlet di PowerShell:

Mentre è comprensibile aspettarsi il parametro -ChildPath per supportare un matrice di percorsi (che non), è importante capire che il design Join-Path 's fondamentalmente diversa da quella di [System.IO.Path]::Combine(), come di Windows PowerShell v5.1 [1] :

  • Join-Path utilizza percorsi di ingresso multipli per generare più uscite invece di interpretare i percorsi di ingresso come componenti di un percorso di uscita singolo.

  • percorsi di ingresso sono coppia (s) di genitore e bambino percorsi, con ogni coppia sempre unito e conseguente nel proprio percorso di output:

    • > Join-Path \foo \bar \foo\bar
      • corto per: Join-Path -Path \foo -ChildPath \bar
      • Nota come PS, a differenza di [System.IO.Path]::Combine(), gestisce un \ iniziale opzionale nel bambino percorso come ti aspetteresti.
  • Mentre il parametro padre-path (-Path) fa sostegno un matrice di percorsi principali, il parametro bambino-path (-ChildPath) non non, anche se quando combinato con il -Resolve parametro e caratteri jolly, può effettivamente risultare in più percorsi figlio.

    • > Join-Path -Path \foo, \baz -ChildPath \bar \foo\bar \baz\bar
    • Si noti come sono stati generati percorsi di uscita, accoppiando ogni percorso genitore con il percorso di un bambino.
  • differenza [System.IO.Path]::Combine(), Join-Path opzionalmente supporta la risoluzione di percorsi jolly con -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
  • Infine vale la pena notare che Join-Path non funziona solo con i percorsi del file system, ma con i percorsi di qualsiasi fornitore di PowerShell [archivio dati gerarchico], applicando la fornitura separatori di percorso appropriati per r.


[1] L'edizione cross-platform PowerShell, PowerShell Nucleo, come di v6.0.0, già fa sostegno un numero arbitrario di componenti figlio, enabling calls such as Join-Path a b c to yield a\b\c (Windows) or a/b/c (Unix), mentre l'edizione nativa per Windows Windows PowerShell a partire dalla versione 5.1 non è ancora disponibile rt it.
Questo nuovo comportamento non è ancora documentato (e non riflette anche la sintassi in base a Join-Path -?), ma potrebbe essere incluso in Windows PowerShell (e quindi tutte le versioni).

+1

Questa dovrebbe essere la risposta accettata. –

Problemi correlati