如何在Powershell中递归截断文件名?



我需要将文件名截断为 35 个字符(包括扩展名(,所以我运行这个脚本,它适用于它自己的目录(PowerShell、Windows 10(。

Get-ChildItem *.pdf | rename-item -NewName {$_.name.substring(0,31) + $_.Extension} 

然后我想应用相同的脚本,包括子目录:

Get-ChildItem -Recurse -Include *.pdf | Rename-Item -NewName {$_.Name.substring(0,31) + $_.Extension}

这个脚本为每个文件都给了我这样的错误:

Rename-Item : Error in input to script block for parameter 'NewName'. Exception when calling "Substring" with the arguments "2": "The index and length must reference a location in the string. Parameter name: length"
On line: 1 Character: 62
+ ... *.pdf | Rename-Item -NewName {$_.Name.substring(0,31) + $_.Extension}
+                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidArgument: (C:Userprsn..._file_name_long.pdf:PSObject) [Rename-Item], ParameterBindingException
+ FullyQualifiedErrorId : ScriptBlockArgumentInvocationFailed,Microsoft.PowerShell.Commands.RenameItemCommand

我试过这个,但它没有在子目录上: 以 255 个字符截断所有文件名的命令

我找到了这个,但它没有答案: https://superuser.com/questions/1188711/how-to-recursively-truncate-filenames-and-directory-names-in-powershell

我认为你不能那样使用 $_。 我认为您必须将其包装在 ForEach 循环中才能使引用以这种方式工作。 完成后,您还必须指定要重命名的文件的路径:

像这样:

Get-ChildItem -Recurse -Include *.pdf -File | 
ForEach-Object{
Rename-Item -Path $_.FullName -NewName ( $_.BaseName.SubString(0, 31) + $_.Extension )
}

请注意,我使用了括号而不是大括号。 如果使用脚本块,则可能无法计算。 还有其他方法可以实现它,但我认为使用括号是最明显的。

请注意,我使用了$_.BaseName而不是名称。 基本名称不包括扩展名。虽然我不知道你的子字符串是如何工作的,但我把它留给你决定。

你可以把它与@Mathias的答案或对它的一些修改结合起来。 这可能会为您提供更好或更可靠的方法来派生新文件名。我还没有测试过它,但它可能看起来像这样:

Get-ChildItem -Recurse -Include *.pdf -File | 
ForEach-Object{        
Rename-Item -Path $_.FullName -NewName ( ($_.Name -replace '(?<=^.{35}).*$') + $_.Extension )
}

使用-replace正则表达式运算符删除前 35 个字符之后的任何内容 - 它将简单地忽略任何没有至少 35 个字符的字符串并按原样返回:

$_.Name -replace '(?<=^.{35}).*$'

正确的错误消息是
Exception calling "Substring" with "2" argument(s): "Index and length must refer to a location within the string.

原因是第二个参数大于文件名的长度。"abc".Substring(0,4)投掷。

$renameTarget = dir -File -Recurse *.pdf | ? { $_.Name.Length -gt 35 }
$renameTarget | Rename-Item -NewName {
$_.name.substring(0, 31) + ".pdf"
}

dir *.pdf -File -Recurse | Rename-Item -NewName {
$_.name.substring(0, [Math]::Min($_.BaseName.length, 31)) + ".pdf"
}

相关内容

最新更新