找不到路径 _ 因为它不存在

Cannot find path _ because it does not exist

我正在尝试在 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.

使用和不使用管理权限都会出现相同的错误。

我需要做什么才能让它发挥作用?

尝试以下操作:

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 common parameter预览操作。一旦您确定该操作将执行您想要的操作,请删除 -WhatIf

  • -Filter '*[1]*' 预过滤 Get-ChildItem 输出以仅包括名称包含子字符串 [1] verbatim 的文件,因为-Filter 参数使用 filesystem-native 通配符语言 not[] 视为元字符.

    • 相比之下,使用 PowerShell 更强大的 wildcard patterns, '*[1]*' would match any name that contains just 1, because the [...] is interpreted as a character set or range. With the -like, the wildcard matching operator 运算符,您必须使用 '*`[1`]*'(转义要使用 ` 逐字解释的元字符)来逐字查找 [1] 个子字符串。
  • -File 将匹配项限制为 files,因为 hardlinks 只支持文件,不支持还有目录。

  • -Path (Join-Path .\[1] $file) 仅使用 一个 -Path 参数 - 而不是仅目录路径 -Path 参数组合使用仅包含文件名的 -Name 参数 - 这确保该参数被视为 文字 (逐字)路径,而不解释通配符元字符,例如 [].

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

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

    • 警告:

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

      • 但是,从 PowerShell 7.2.2 开始,此更改尚未实现,不幸的是,目标路径包含 [] 目前 完全损坏 - 参见 GitHub issue #14534.

        • 从 PowerShell 7.2.2 开始,您必须转义 两次(!) 才能使其工作:([WildcardPattern]::Escape([WildcardPattern]::Escape($path)))

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

因此,您可以使 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-Force 不会 按需创建目标目录。另一方面,与 New-Item-Target 不同,Move-Item-Destination 更明智地解释其论点 字面 (逐字)参数.