首页 > 解决方案 > 找不到路径_,因为它不存在

问题描述

我正在尝试在 powershell 中创建小脚本,该脚本将移动文件和目录以更正本地化。我做了以下命令:

Get-ChildItem -Path '.\list\' | ForEach-Object { if ($($_.Name) -like '*[1]*') {
$file = $($_.Name)
$path = $($_.FullName)
echo "$file  ==>  $path"
Move-Item -Path $path -Destination .\[1]\}}

它会检测到正确的文件和目录,但不会移动它们。
然后我决定稍微修改命令并创建硬链接:

Get-ChildItem -Path '.\list\' | ForEach-Object { if ($($_.Name) -like '*[1]*') {
$file = $($_.Name)
$path = $($_.FullName)
echo "$file  ==>  $path"
New-Item -Path ".\``[1``]\" -Name $file -Type HardLink -Target "$path"}}

我收到了以下回复(只剪了 1 个循环):

[1] dir1  ==>  D:\test_move\list\[1] dir1
New-Item:
Line |
   5 |  New-Item -Path ".\``[1``]\" -Name $file -Type HardLink -Target "$path …
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Cannot find path 'D:\test_move\list\[1] dir1' because it does not exist.

无论有无管理权限,都会出现相同的错误。

我必须做些什么才能让它发挥作用?

标签: powershellhardlinknew-item

解决方案


尝试以下操作:

Get-ChildItem -LiteralPath .\list -File -Filter '*[1]*' | ForEach-Object { 
  $file = $_.Name
  $path = $_.FullName
  "$file  ==>  $path" # implicit `echo` aka `Write-Output`
  New-Item -Force -Type HardLink `
           -Path (Join-Path .\[1] $file) `
           -Target ([WildcardPattern]::Escape($path)) ` # !! see PowerShell Core comments below
           -WhatIf
}

注意:上面命令中的-WhatIf常用参数是预览操作。-WhatIf 一旦您确定该操作将执行您想要的操作,请删除。

  • -Filter '*[1]*'预过滤Get-ChildItem输出以仅包含名称包含子字符串[1] verbatim的文件,因为该-Filter参数使用文件系统原生通配符语言,不[视为]元字符。

    • 相比之下,使用 PowerShell 更强大的通配符模式'*[1]*'将匹配任何包含 just 的名称1,因为[...]被解释为字符集或范围。使用通配符匹配运算-like符运算符,您必须使用(转义要逐字解释的元字符)来查找逐字子字符串。'*`[1`]*'`[1]
  • -File将匹配项限制为files,因为硬链接仅支持文件,不支持目录。

  • -Path (Join-Path .\[1] $file)使用-Path参数 - 而不是仅目录路径参数-Path与仅文件名参数结合使用-Name- 这可确保将参数视为文字(逐字)路径,而无需解释通配符元字符,例如[and ]

    • 遗憾的是,结合-Pathwith-Name会导致-Path参数被解释为通配符模式
  • -Force如果需要,根据需要创建目标目录,但请注意,它还将替换任何预先存在的目标文件。

  • 仅限Windows PowerShell([WildcardPattern]::Escape($path))转义目标路径,以便在解释为通配符模式时逐字处理它,不幸的是,该参数被解释为。不执行此转义会提示您看到的错误。-Target

    • 警告

      • PowerShell [Core] 7+中, GitHub 提案 #13136中批准了一项重大更改,以更明智地-Target参数视为文字(逐字)路径,在这种情况下,您只需使用-Target $path.

      • 但是,从 PowerShell 7.1 开始,此更改尚未实现,不幸的是,目标路径包含[并且]当前完全损坏- 请参阅GitHub 问题 #14534

请注意,许多(但不是全部)文件处理 cmdlet 提供了一个-LiteralPath参数来显式传递要按字面意思(逐字)采用的路径,而该 -Path参数(通常是第一个位置参数的隐含参数)旨在接受通配符模式。

因此,您可以Move-Item按照以下方式使用您的原始方法:

# Ensure that the target dir. exists.
# No escaping needed for -Path when not combined with -Name.
$null = New-Item -Type Directory -Path .\[1] -Force 

# Move the file, targeted with -LiteralPath, there.
# No escaping needed for -Destination.
Move-Item -LiteralPath $path -Destination .\[1]\

注意:与,不同New-Item,不会按需创建目标目录。另一方面,与'参数不同, '更明智地按字面意思(逐字)解释其参数。Move-Item-ForceMove-Item-DestinationNew-Item-Target


推荐阅读