move-item在循环中不起作用

时间:2011-03-16 16:26:39

标签: loops powershell move

ls *.gif | Foreach { $newname = $_.Name -replace '\[','' -replace '\]',''
                     write-host $_.Name $newname
                     move-Item -Path $_.Name -Destination $newname; }
ls *.gif

因此,在尝试帮助某人使用[]重命名文件时,我发现move-item在循环中不起作用。它似乎在循环之外工作得很好。

想法?

4 个答案:

答案 0 :(得分:7)

更新:根据下面的评论,我想澄清一下:文件名中的特殊字符要求您使用-LiteralPath参数。 -Path无法处理这些字符。在循环之外,-Path有效,因为你使用`来转义特殊字符。在走过一个集合时,这是不可能的。

在循环中,您需要使用-LiteralPath参数而不是-Path。

-LiteralPath <string[]>
    Specifies the path to the current location of the items. Unlike Path, the value of
    LiteralPath is used exactly as it is typed. **No characters are interpreted as 
    wildcards. If the path includes escape characters, enclose it in single quotation 
    marks.** Single quotation marks tell Windows PowerShell not to interpret any 
    characters as escape sequences.

所以,这将是:

GCI -Recurse *.txt | % { Move-Item -LiteralPath $_.FullName -Destination "SomenewName" }

答案 1 :(得分:3)

如果您使用PowerShell的管道绑定功能,则可以使这更加简单,并且无需显式Foreach-Object,例如:

ls *.gif | Move-Item -Destination {$_ -replace '\[|\]',''} -WhatIf

这是有效的,因为LiteralPath参数设置为绑定ByPropertyName。但是您可能想知道,它从Get-ChildItem(别名ls)的输出中获取了名为“LiteralPath”的属性。好吧,它没有找到该属性名称,但是LiteralPath参数定义的别名为PSPath,它确实存在于Get-ChildItem输出的每个对象上。这就是它与LiteralPath参数的联系。这里的另一个速度提示是因为Destination参数也是管道绑定(ByPropertyName),您可以使用scriptblock来提供值。在该脚本块中,您可以访问管道对象。

在scriptblock内部,它使用-replace运算符根据原始全名提出新名称。虽然在这种情况下我可以使用$_.FullName甚至$_.Name(假设您想要在同一目录中重命名文件),但我只使用$_。由于-replace是一个字符串运算符,因此在使用之前它会将$_强制转换为字符串。你可以通过执行来看看它会是什么:

ls *.gif | Foreach {"$_"}

在这种情况下,这是完整的路径,但你必须要小心,因为你并不总是得到完整的路径,例如:

ls | Foreach {"$_"}

只显示文件名。在你的例子中(重命名为相同的目录)这没关系,但在其他情况下确实如此。在脚本中明确地使用$_.Name$_.FullName可能是一个好习惯,但是当在控制台上破解这些东西时,我倾向于只使用$_。俗话说:这是一根尖锐的棍子,不要捅你的眼睛适用于此。 : - )

答案 2 :(得分:0)

您可以在this Microsoft article上的路径字符串中找到有关“[”角色的“官方”信息。

或者在google中查找:Windows PowerShell本周提示:“按字面意思拍摄内容(如文件路径)”。

我不清楚的唯一提示是Rename-Item不支持LiteralPath,我们可以使用Move-Item重命名文件或目录。

JP

答案 3 :(得分:0)

这对我有用(至少在我的情况下。

Move-Item -literalpath $_.FullName -Destination ( ( ( (Join-Path -Path (Get-Location) -ChildPath $_.BaseName) -replace "\[","`[") -replace "\]","`]") ) 

有数百部电影及其关联的字幕存储没有文件夹。决定将每部电影和字幕放在自己的文件夹中

完整代码

Get-ChildItem -File | % 
{
    if(Test-Path -LiteralPath ( Join-Path -Path (Get-Location) -ChildPath $_.BaseName ))
    {
         Move-Item -literalpath $_.FullName -Destination ( ( ( (Join-Path -Path (Get-Location) -ChildPath $_.BaseName) -replace "\[","`[") -replace "\]","`]") ) 
    }
    else
    {
        New-Item ( Join-Path -Path (Get-Location) -ChildPath $_.BaseName ) -ItemType Directory 
        Move-Item $_ -Destination ( Join-Path -Path (Get-Location) -ChildPath $_.BaseName )
    }

}