PowerShell批量文件重命名中的奇怪行为

问题描述:

我是PowerShell的新手,最近我尝试重命名文件夹中的120个文件,并遇到奇怪的行为。PowerShell批量文件重命名中的奇怪行为

我有什么是从0001.txt,0002.txt,... 0120.txt命名的文件共120个文件。我想在每个文件名前添加一个'a'。我想出了这个命令:

ls | ren -newname {$_.name -replace '(\d+)','a$1'} 

但执行后,我得到了许多错误是这样的:

“指定的路径,文件名,或者两者都太长完全合格的文件名必须小于260"

当我看着我的文件夹中,我得到的是从

aaaaaaaaaaaaaaaaaaaaaaaaa(repeat until it hit system limit on path length)....a0001.txt 
... 
... 
... 
aaaaaaaaaaaaaaaaaaaaaaaaa(repeat until it hit system limit on path length)....a0120.txt 
文件名

使用-cf开关进行进一步检查后,事实证明,PowerShell将递归尝试重命名过程。第一次重命名所有120个文件后,它再次将命令应用于a0001.txt,在文件名前有效地添加了另一个'a'。这一直持续下去,直到达到路径长度限制并报告错误。

任何人都可以告诉我,如果我的重命名命令有什么问题吗?

管到FOREACH-对象(速记%{})到质重命名文件。如果你只是想前面加上字母一个将每个文件名,你并不需要一个正则表达式,所有你需要做的是这样的:

Get-ChildItem | %{Rename-Item $_ ('a' + $_.name)} 

用你喜欢的别名:

ls | %{ren $_ ('a' + $_.name)} 

要用正则表达式来做,使用($_.name -replace '^','a')更简单。如果使用正则表达式的原因是目录中有其他文件,并且您只想重命名以一串数字和.txt扩展名命名的文件,请注意您正在使用的正则表达式会预先计划一个a到任何连续数字串。例如,agent007.txt将被重命名为agenta007.txt。你应该只用你想要的格式匹配正则表达式:'^(\d+)\.txt'

还要注意,通过使用正则表达式在-NewName说法代替,你重命名不正则表达式匹配相同的名称,它已经拥有的每个文件。没什么大不了的120个文件,但我会过滤文件提前上市:

Get-ChildItem | ?{$_ -match '^(\d+)\.txt'} | %{Rename-Item $_ ('a' + $_.name)} 

UPDATE:似乎有使用PowerShell 3.0中的错误,可能会导致批量重命名文件失败在某些条件下。如果通过将目录列表重命名为Rename-Item来重命名文件,则任何文件被重命名为按字母顺序高于其当前名称的文件都将通过其新名称进行重新处理,因为它稍后在目录列表中遇到。这可能会导致相同的文件重复重命名,直到完整路径的长度超过260个字符的最大值并引发错误。

例如,请注意,如果附加字母a而不是前置,则没有问题。如果文件被命名为B0001B0002等,一个被预先计划,不会出现重复的再处理信

Get-ChildItem | %{Rename-Item $_ ($_.name + 'a')} 

:这适用于任意数量的文件。但是,如果前置字母c确实存在。

以下命令将单个一个到任意数量的文件的开头,如果他们的名字与b开始:

Get-ChildItem | %{Rename-Item $_ ('a' + $_.name)} 

由于相同的文件,其名称与B开头,下面的命令预先考虑信ç反复直到达到长度限制:

Get-ChildItem | %{Rename-Item $_ ('c' + $_.name)} 

这只发生在包含一定数量或更高文件的列表中。 OP表示,如果他将文件数量减少到20个以下,他就没有问题。我发现阈值为37(36个文件或更少,不会发生重新处理)。我还没有确定所有适用案例的数字是否相同,还是取决于更具体的因素。

稍后我会详细说明这一点,并且一旦我更确切地确定了此问题的参数,就向Microsoft提交错误报告。

解决方法:过滤器从上市获取-ChildItem位置对象使得新的文件名被排除在外。在更新部分之前,上面的命令的最后一个版本在PowerShell 3.0中工作。据推测,重新命名的文件通过新名称重新引入到管道中,并再次处理,但由于新名称与筛选器?{$_ -match '^(\d+)\.txt'}不匹配,所以它们在第二次通过管道时不会重命名,并且不会再次重新处理。

+0

感谢您的回答,您的解释对于像我这样的新手来说非常翔实。你的命令在PowerShell版本2上工作(如我的)。但它在PowerShell的版本3上给出了相同的行为。我可以知道您使用的是哪个版本的PowerShell?而在版本3中,如果我将该文件夹中的文件减少到20个文件,这种奇怪的行为就不会出现。我可能刚刚在PowerShell中发现了一个错误,或者我有一个错误的内存芯片 –

+0

哇,你是对的!这*是* PS 3中的一个错误。我在两个版本中进行了测试,但只有少量的文件。随着数量的增加,看起来正在发生的事情是,如果一个文件被重新命名为按字母顺序排列的更高的文件,它会再次用新名称进行处理 - 这种情况会在相同的文件中反复出现。评论太长,但我会更新我的答案,并向Microsoft提交错误报告。现在,我可以告诉你,我的答案中的最后一个版本和** where过滤器一起工作,因为新名称与模式不匹配,因此不会重新处理。 –

+0

感谢您的反馈和漫长的更新。感觉自己是第一个发现bug的人。 :)只是想知道为什么这个bug还没有被带出来。 –