PoshCode / PowerShellPracticeAndStyle

The Unofficial PowerShell Best Practices and Style Guide
https://poshcode.gitbooks.io/powershell-practice-and-style
Other
2.24k stars 289 forks source link

File Path Formatting #84

Open jonkyops opened 7 years ago

jonkyops commented 7 years ago

Is there a best practice way of handling file path formatting? These are the ways I know how to format them right now, assuming a path of '\Server1\Share1\SubFolder1\File1.txt'

$Server = 'Server1'
$Share = 'Share1'
$SubFolder = 'SubFolder1'
$File = 'File1.txt'

Join-Path

  1. Piping $FullPath = Join-Path -Path $Server -ChildPath $Share | -ChildPath $SubFolder | -ChildPath $File

  2. MultiLine

    $Path1 = Join-Path -Path $Server -ChildPath $Share
    $Path2 = Join-Path -Path $Path -ChildPath $SubFolder
    $FullPath = Join-Path -Path $Path -ChildPath $File

-Join parameter $FullPath = '\', $Server, $Share, $SubFolder, $File -join '\'

String interpolation, adding an underscore after the file name to show variable expansion, I know it's not valid. $FullPath = "\\$Server\$Share\$SubFolder\$($File)_"

String formatting $FullPath = '\\{0}\{1}\{2}\{3}' -f $Server, $Share, $SubFolder, $File

String concatenation $FullPath = '\\' + $Server + '\' + $Share + '\' + $SubFolder + '\' + $File

.NET class [io.path]::combine("\\$Server", $Share, $SubFolder, $File)

rkeithhill commented 7 years ago

Somebody (was it @dlwyatt) modified Join-Path in PS Core to behave like Path.Combine:

Join-Path Server1 Share SubFolder File
Server1/Share/SubFolder/File

Would love to see this backported to Windows PowerShell.

BTW while the string interpolation appeals to me because it is readable/obvious, it doesn't handle the scenario of different path dir separator chars e.g. \ vs /. Join-Path does this for you. And while PowerShell generally doesn't care which dir sep char you use, native utilities typically aren't so forgiving.

Jaykul commented 7 years ago

On the up-side: Join-Path fixes path separators for you. The good news about this is that you can combine it with any of the other methods to normalize all the slashes.

On the down-side: it does this by resolving the Provider for the path to determine what the separator should be, and therefore does not work with rooted paths if the path doesn't exist on the local system. That is, you can't do Join-Path "X:\Temp" "SubFolder" if you don't have an X: drive.

Basically nothing will fix the path separators without caring about drive names that don't exist except [IO.Path]::GetFullPath -- but even that one only works if your drive names are single letters.

What we do currently is a mishmash mix of interpolation and the -join operator passed to Join-Path to fix our slashes for us. We actually have an internal wrapper for Join-Path which uses Split-Path $Path -IsAbsolute (why is that on Split-Path, and not Test-Path?) and then rips off the drive qualifier with $Drive = Split-Path $Path -Qualifier -ErrorAction Ignore and $Path = Split-Path $Path -NoQualifier and then uses Join-Path and puts the $Drive qualifier back at the end...

Objections commented 5 years ago

There have been some improvements on this in powerfully 6+ with -AdditionalChildPath

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/join-path?view=powershell-6#optional-parameters