首页 > 解决方案 > 如何在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:\User\prsn..._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

标签: windowspowershellcmd

解决方案


我不认为你可以这样使用 $_ 。我认为您必须将其包装在 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 )
        }

推荐阅读