如何使用 join-Path 将两个以上的字符串组合成一个文件路径?

如果我想把两个字符串组合成一个文件路径,我可以这样使用 Join-Path:

$path = Join-Path C: "Program Files"
Write-Host $path

如果我想对多于两个字符串执行此操作:

$path = Join-Path C: "Program Files" "Microsoft Office"
Write-Host $path

PowerShell 抛出一个错误:

连接路径: 找不到接受参数“ MicrosoftOffice”的位置参数。
At D: users ma my _ script. ps1:1 char: 18
+ $path = join-path < < < C: “ Program Files”“ Microsoft Office”
+ Category oryInfo: InvalidArgument: (:)[ join-Path ] ,Parameter terBindingException
+ FullyQualifiedErrorId:
. 命令. 加入路径命令

我尝试使用字符串数组:

[string[]] $pieces = "C:", "Program Files", "Microsoft Office"
$path = Join-Path $pieces
Write-Host $path

但是 PowerShell 提示我输入子路径(因为我没有指定 -childpath参数) ,例如“ some path”,然后创建三个文件路径,

C:\somepath
Program Files\somepath
Microsoft Office\somepath

这也不对。

136050 次浏览

联接路径并不是您正在寻找的。它有多种用途,但不是你正在寻找的。使用 join-Path 进行聚会的一个例子:

Join-Path C:\hello,d:\goodbye,e:\hola,f:\adios world
C:\hello\world
d:\goodbye\world
e:\hola\world
f:\adios\world

您可以看到它接受一个字符串数组,并将子字符串连接到每个创建完整路径的子字符串。在您的示例中,$path = join-path C: "Program Files" "Microsoft Office"。由于传递了三个位置参数,而 join-path只接受两个,因此出现了错误。你要找的是 -join我觉得这是个误会。考虑一下你的例子:

"C:","Program Files","Microsoft Office" -join "\"

-Join获取项数组,并将它们与 \连接成一个字符串。

C:\Program Files\Microsoft Office

小小的打捞尝试

是的,我同意 这个答案更好,但我的仍然可以工作。注释表明斜杠可能存在问题,因此为了与我的连接方法保持一致,您也可以这样做。

"C:","\\Program Files\","Microsoft Office\" -join "\" -replace "(?!^\\)\\{2,}","\"

因此,如果有问题与额外的斜杠,它可以处理,只要他们不在字符串的开头(允许 UNC路径)。[io.path]::combine('c:\', 'foo', '\bar\')不会像预期的那样工作,我的可以解释。两者都需要适当的字符串作为输入,因为您无法考虑所有场景。考虑这两种方法,但是,是的,另一个评分较高的答案更简洁,我甚至不知道它的存在。

另外,我想指出的是,我的回答解释了 OP 所做的是错误的,除了提供了解决核心问题的建议之外。

可以使用.NET 路径类:

[IO.Path]::Combine('C:\', 'Foo', 'Bar')

因为 join-Path 可以通过管道传送一个路径值,所以您可以将多个 join-Path 语句通过管道传送到一起:

Join-Path "C:" -ChildPath "Windows" | Join-Path -ChildPath "system32" | Join-Path -ChildPath "drivers"

它可能没有您希望的那么简洁,但是它是完全 PowerShell 的,并且相对容易阅读。

如果你还在使用。NET 2.0,那么 [IO.Path]::Combine将不会有需要连接两个以上部分的 params string[]过载,您将看到错误 找不到“组合”和参数计数的重载: “3”。

虽然不那么优雅,但是纯 PowerShell 解决方案是手动聚合路径部分:

Join-Path C: (Join-Path  "Program Files" "Microsoft Office")

或者

Join-Path  (Join-Path  C: "Program Files") "Microsoft Office"

这里有一些东西可以满足您在为 ChildPath 使用字符串数组时的需要。

$path = "C:"
@( "Program Files", "Microsoft Office" ) | %{ $path = Join-Path $path $_ }
Write-Host $path

输出

C:\Program Files\Microsoft Office

我发现的唯一警告是 $path 的初始值必须有一个值(不能为 null 或空)。

你可以这样使用它:

$root = 'C:'
$folder1 = 'Program Files (x86)'
$folder2 = 'Microsoft.NET'


if (-Not(Test-Path $(Join-Path $root -ChildPath $folder1 | Join-Path -ChildPath $folder2)))
{
"Folder does not exist"
}
else
{
"Folder exist"
}

或者您可以为它编写自己的函数(这正是我最后所做的)。

function Join-Path-Recursively($PathParts) {
$NumberOfPathParts = $PathParts.Length;


if ($NumberOfPathParts -eq 0) {
return $null
} elseif ($NumberOfPathParts -eq 1) {
return $PathParts[0]
} else {
return Join-Path -Path $PathParts[0] -ChildPath $(Join-Path-Recursively -PathParts $PathParts[1..($NumberOfPathParts-1)])
}
}

然后你可以这样调用函数:

Join-Path-Recursively -PathParts  @("C:", "Program Files", "Microsoft Office")
Join-Path-Recursively  @("C:", "Program Files", "Microsoft Office")

这样做的优点是与普通的 join-Path 函数具有完全相同的行为,并且不依赖于。NET 架构。

下面的方法比管道连接路径语句更简洁:

$p = "a"; "b", "c", "d" | ForEach-Object -Process { $p = Join-Path $p $_ }

$p 然后保存连接的路径‘ a b c d’。

(我刚刚注意到,这和迈克•费尔(Mike Fair)的方法完全一样,抱歉。)

下面是另外两种编写纯 PowerShell 函数将任意数量的组件连接到路径中的方法。

第一个函数使用一个数组来存储所有组件,然后使用 foreach 循环来组合它们:

function Join-Paths {
Param(
[Parameter(mandatory)]
[String[]]
$Paths
)
$output = $Paths[0]
foreach($path in $Paths[1..$Paths.Count]) {
$output = Join-Path $output -ChildPath $path
}
$output
}

因为路径组件是数组中的元素,而且是单个参数的所有部分,所以它们必须用逗号分隔。用法如下:

PS C:\> Join-Paths 'C:', 'Program Files', 'Microsoft Office'
C:\Program Files\Microsoft Office


编写这个函数的一种更简单的方法是使用内置的 $args变量,然后使用 Mike Fair 的方法将 foreach 循环折叠成一行。

function Join-Paths2 {
$path = $args[0]
$args[1..$args.Count] | %{ $path = Join-Path $path $_ }
$path
}

与以前版本的函数不同,每个路径组件是一个单独的参数,因此只需要一个空格来分隔参数:

PS C:\> Join-Paths2 'C:' 'Program Files' 'Microsoft Office'
C:\Program Files\Microsoft Office

从 PowerShell 6.0开始,join-Path 有一个名为 -AdditionalChildPath新参数,可以是 将路径的多个部分组合在一起。要么通过提供额外的参数,要么通过提供元素列表。

来自 文件的例子:

Join-Path a b c d e f g
a\b\c\d\e\f\g

所以在 PowerShell 6.0及以上版本中

$path = Join-Path C: "Program Files" "Microsoft Office"

果然有效!