我正在尝试在 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.
无论有没有管理权限都会出现相同的错误。
我需要做什么才能让它发挥作用?
答案 0 :(得分:0)
尝试以下操作:
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
参数使用一种文件系统原生通配符语言,不将 [
和 ]
视为元字符。
'*[1]*'
将匹配任何仅包含 1
的名称,因为 [...]
被解释为字符集或范围。使用 -like
,wildcard matching operator 运算符,您必须使用 '*`[1`]*'
(转义要使用 `
逐字解释的元字符)来逐字查找 {{1} } 子字符串。[1]
将匹配项限制为文件,因为硬链接仅支持文件,不支持目录。
-File
使用 only -Path (Join-Path .\[1] $file)
参数 - 而不是仅目录路径 -Path
参数与仅文件名 {{ 1}} 参数 - 确保参数被视为 literal(逐字)路径,而不解释通配符元字符,例如 -Path
和 -Name
。
[
与 ]
结合会导致 -Path
参数被解释为通配符模式。-Name
按需创建目标目录(如果需要),但请注意,它还会替换任何预先存在的目标文件。
仅适用于 Windows PowerShell:-Path
转义目标路径以便在解释时逐字处理它作为通配符模式,不幸的是,-Force
参数被解释为。不执行此转义会提示您看到的错误。
警告:
在 PowerShell [Core] 7+ 中,GitHub proposal #13136 中的一项重大更改已获批准 - 更明智地 - 处理 { {1}} 参数作为文字(逐字)路径,在这种情况下,您可以简单地使用 ([WildcardPattern]::Escape($path))
。
但是,从 PowerShell 7.1 开始,此更改尚未实施,不幸的是,针对包含 -Target
和 -Target
的路径的目标目前已完全中断 - 参见GitHub issue #14534。
请注意,许多(但不是全部)文件处理 cmdlet 提供 -Target $path
参数以显式传递要采用的路径字面(逐字),而 [
参数- 通常第一个位置参数的隐含参数 - 旨在接受通配符模式。
因此,您可以按照以下方式使用 Move-Item
进行原始方法:
]
注意:与 -LiteralPath
不同,-Path
的 # 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
的 Move-Item
更明智地解释其参数字面(逐字)。< /p>