使用PowerShell递归重命名文件

9
调用这个PowerShell命令时,出现错误让我很困扰。
Prompt> get-childitem -recurse ./ *NYCSCA* |  where-object { $_.Name -like
 "*NYCSCA*" } |  rename-item $_ -newname $_.Name.Replace(" ","_") -whatif

以下是回复内容:

You cannot call a method on a null-valued expression.
At line:1 char:140
+ get-childitem -recurse ./ *NYCSCA* |  where-object { $_.Name -like "*NYCSCA*" } | select FullName | rename-item $_ -n
ewname $_.Name.Replace <<<< (" ","_") -whatif
    + CategoryInfo          : InvalidOperation: (Replace:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

如果我删除最后一部分,我会得到一个文件列表。有什么线索吗?显然我还没有掌握PowerShell。
注意:我试图将这个问题发布到超级用户,但该网站现在一直出现故障 - 不允许我添加这个确切的问题。
这是一个大大简化的例子。我甚至无法使这个经典示例工作。
gci  *NYCSCA*  | ren $_ ($_.Name).Replace("foo","bar")

谢谢 @JNK,%解决了问题。这是我需要的解决方案,如果你有兴趣:

gci -recurse | where-object{ $_.Name -like "*NYCSCA*"} | %{rename-item $_.FullName $_.FullName.Replace("NYCSCA","SDUSD") }

请查看https://dev59.com/-GEi5IYBdhLWcg3wIJJH#21614001 - Rory
2个回答

8
我认为您需要使用foreach-object:
get-childitem -recurse ./ *NYCSCA* |  where-object { $_.Name -like
 "*NYCSCA*" } | % {rename-item $_ -newname $_.Name.Replace(" ","_") -whatif}

管道数组不能被重命名为集合。


是的!就是这样 - 谢谢。我需要更好地理解集合和项之间的区别。但这很棒! - Daniel Williams
很高兴能够帮到你。每当我的管道无法工作时,我的第一步就是尝试使用foreach-object。 - JNK
1
当 PowerShell 跳转到一个文件夹进行重命名时,它会抱怨该文件不存在。我该如何基于你的例子解决这个问题? - The Muffin Man
@TheMuffinMan 我建议你发布一个新问题来询问。这可能与你使用的确切语法有关。 - JNK
这个命令似乎不能很好地处理子目录,正如@TheMuffinMan所报告的那样。请参见https://dev59.com/-GEi5IYBdhLWcg3wIJJH#21614001。 - Rory

5
这里是仅重命名文件的简化版本。
Get-ChildItem -Filter *NYCSCA* -Recurse |
 Where-Object {!$_.PSIsContainer} | 
 Rename-Item -NewName { $_.Name.Replace(' ','_') } -WhatIf

(Edit: line breaks added for clarity)


1
这里的真正区别在于在 rename-item 参数中使用代码块 {...},以允许引用 $_(这也是为什么 foreach-object 也提供了一种解决方案)。 - Richard
True,foreach-object可以完成任务,但会增加开销(并且速度较慢)。 - Shay Levy
有趣的是,这样可以让rename-item将其参数视为一个集合,而不是在foreach的一系列操作中调用rename-items。 - Daniel Williams

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接