首页 > 解决方案 > 如何从文件名中删除最后 X 个字符

问题描述

寻求帮助编写一个脚本,该脚本将从文件名的末尾删除特定数量的字符。在我的具体困境中,我有几十个格式如下的文件:

1234567 XKJDFDA.pdf

5413874 KJDFSXZ.pdf

……等等等等。

我需要删除最后 7 个字母字符以保留 7 位数字作为文件名。通过另一个发布的问题,我能够找到一个脚本,该脚本将删除文件名开头的前X个数字,但我很难修改它以从末尾删除:

get-childitem *.pdf | rename-item -newname { [string]($_.name).substring(x) }

任何和所有相关的帮助将不胜感激。

尊敬,

标签: powershellcmdlet

解决方案


$RootFolder = '\\server.domain.local\share\folder'
Get-ChildItem -LiteralPath $RootFolder -Filter '*.pdf' | 
    Where-Object { $_.psIsContainer -eq $false } | # No folders
    ForEach-Object { 
        if ($_.Name -match '^(?<BeginningDigits>\d{7})\s.+\.pdf$' ) {
            $local:newName = "$($Matches['BeginningDigits'])$($_.Extension)"
            return Rename-Item -LiteralPath $_.FullName -NewName $local:newName -PassThru
            }    
        } |
    ForEach-Object {Write-Host "New name: $($_.Name)"}

如果文件名与“ <FilenameBegin><SevenDigits><Space><Something>.pdf<FilenameEnd>”匹配,则将其重命名为“ <SevenDigits>.<KeepExtension>”。这使用带有命名选择组的正则表达式(<BeginningDigits>是组名)。请注意,由于 RegExp 的使用,这是最占用 CPU 的算法,但如果您有一次性运行或文件量很少,则没有任何意义。否则,如果您有很多文件,我建议在 RegExp 检查之前添加Where-Object { $_.BaseName.Length -gt 7 } | beforeif (.. -match ..)以过滤掉短于 7 个符号的文件,以最大限度地减少 CPU 使用率(字符串长度检查比 RegExp 消耗的 CPU 更少)。您也可以\.pdf从 RegExp 中删除以最小化 CPU 使用率,因为您已经拥有此过滤器Get-ChildItem

如果您严格需要匹配“ <7digits><space><7alpha>.pdf”,则应将 RegExp 表达式替换为'^(?<BeginningDigits>\d{7})\s[A-Z]{7}\.pdf$'


$RootFolder = '\\server.domain.local\share\folder'
@( Get-ChildItem -LiteralPath $RootFolder -Filter '*.pdf' ) | 
    Where-Object { $_.psIsContainer -eq $false } | # No folders
    Where-Object { $_.BaseName.Length -gt 7 } | # For files where basename (name without extension) have more than 7 symbols)
    ForEach-Object { 
            $local:newName =  [string]::Join('', $_.BaseName.ToCharArray()[0..6] ) 
            return Rename-Item -LiteralPath $_.FullName -NewName $local:newName -PassThru
        } |
    ForEach-Object {Write-Host "New name: $($_.Name)"}

替代方案:使用字符串拆分连接:重命名所有文件,其名称不带扩展名 > 7 个符号为前 7 个符号(不考虑是否为数字),保留扩展名。这是愚蠢的算法,因为 Substring 更快。这只是可以帮助学习使用子阵列选择[x..y]

请注意,我们在使用[x..y]in之前检查字符串长度 > 7 Where-Object { $_.BaseName.Length -gt 7 }。否则,当名称短于 7 个符号并且我们尝试采用第 7 个符号时,我们会遇到错误。


$RootFolder = '\\server.domain.local\share\folder'
@( Get-ChildItem -LiteralPath $RootFolder -Filter '*.pdf' ) | 
    Where-Object { $_.psIsContainer -eq $false }
    Where-Object { $_.BaseName.Length -gt 7 } | # For files where basename (name without extension) have more than 7 symbols)
    ForEach-Object { 
            $local:newName = $x[0].BaseName.Substring(0,7)
            return Rename-Item -LiteralPath $_.FullName -NewName $local:newName -PassThru
        } |
    ForEach-Object {Write-Host "New name: $($_.Name)"}

替代方案:使用子字符串。将所有不带扩展名> 7个符号的文件重命名为前7个符号(不考虑是否为数字),保留扩展名。

.Substring(0,7)# 0 - 第一个符号的位置,7 - 需要多少个符号。请注意,我们在使用 substring in 之前检查字符串长度 > 7 Where-Object { $_.BaseName.Length -gt 7 }。否则,当名称短于 7 个符号时,我们会遇到错误


推荐阅读