我是PowerShell新手,最近我尝试重命名一个文件夹中的120个文件,我遇到了一种奇怪的行为。
我有一个名为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‘。这个过程一直持续到达到路径长度的极限,并报告了错误。
有人能告诉我我的重命名命令有什么问题吗?
发布于 2013-08-18 16:52:29
将管道传送到Foreach-Object (简写为%{ })到重命名文件.如果您只想在每个文件名前加上字母a,则不需要正则表达式,只需如下所示:
Get-ChildItem | %{Rename-Item $_ ('a' + $_.name)}
使用您喜欢的别名:
ls | %{ren $_ ('a' + $_.name)}
要用正则表达式来实现它,使用($_.name -replace '^','a')
就更简单了。如果使用regex的原因是目录中有其他文件,并且只想重命名以数字字符串和.txt扩展名命名的文件,请注意,所使用的正则表达式将将a置于任何连续数字字符串的前面。例如,agent007.txt将被重命名为agenta007.txt.您应该让regex只匹配您想要的格式:'^(\d+)\.txt'
。
还请注意,通过在-NewName参数中使用regex替换,可以将不匹配regex的每个文件重命名为与其已有名称不匹配的文件。对于120个文件来说,没什么大不了的,但我会预先过滤文件列表:
Get-ChildItem | ?{$_ -match '^(\d+)\.txt'} | %{Rename-Item $_ ('a' + $_.name)}
更新:在PowerShell 3.0中似乎有一个错误,它可能导致在某些情况下大容量文件重命名失败。如果通过将目录列表管道化为Rename-Item,来重命名文件,则任何按字母顺序高于当前名称的文件都将被新名称重新处理,因为在目录列表后面会遇到该文件。这可能导致重复重命名相同的文件,直到完整路径的长度超过260个字符的最大值,并引发错误。
例如,请注意,如果字母a被附加而不是加在前面,那么就没有问题。这适用于任意数量的文件:
Get-ChildItem | %{Rename-Item $_ ($_.name + 'a')}
如果文件名为b0001、b0002等,并且字母a是前缀,则不会发生重复的再处理。但是,如果字母c加在前面,就会发生。
以下命令将单个a添加到任意数量文件的开头,如果它们的所有名称都以b开头
Get-ChildItem | %{Rename-Item $_ ('a' + $_.name)}
给定相同的文件(名称以b开头),下面的命令重复地在字母c前面加上字母c,直到达到长度限制为止:
Get-ChildItem | %{Rename-Item $_ ('c' + $_.name)}
这种情况只发生在包含一定数量或更高文件的列表中。OP说,如果将文件数量减少到少于20个,他就不会有问题。我发现阈值是37 (有36个或更少的文件,不会发生重新处理)。我还没有确定所有适用案例的数字是相同的,还是取决于更具体的因素。
稍后,我将详细说明这一点,并在更具体地确定此问题的参数后,向Microsoft提交一份bug报告。
Get-ChildItem解决方案:使用Where-Object筛选来自的列表,从而排除新的文件名。上述命令在更新部分之前的最后一个版本在PowerShell 3.0中工作。据推测,重命名的文件将通过它们的新名称重新导入管道,并再处理一次,但由于新名称与筛选器?{$_ -match '^(\d+)\.txt'}
不匹配,因此它们不会在第二次通过管道时被重命名,也不会再次重新处理。
发布于 2020-02-21 13:05:47
我建议一个简单的解决方案,它对我来说很好,不需要任何额外的正则表达式和过滤,有任何文件号。
$files = Get-ChildItem; $files | ForEach-Object {Rename-Item $_ ('a' + $_.Name)}
发布于 2020-02-21 14:36:41
或者在ls或get-childitem项目周围使用括号,以便它首先完成。此问题在powershell 6中得到解决。
(ls) | ren -newname {$_.name -replace '(\d+)','a$1'}
下面是另一种在文件名前加上'a‘的方法:
(ls) | ren -newname { $_.name -replace '^','a' } -whatif
或者使用ps 6 -replace (然后不需要括号):
ls | ren -newname { $_.name -replace '.+',{"a$_"} } -whatif
https://stackoverflow.com/questions/18301293
复制相似问题