Ric
Ric

Reputation: 33

How to remove last X number of character from file name

Looking for help writing a script that will remove a specific number of characters from the end of a file name. In my specific dilemma, I have dozens of files with the following format:

1234567 XKJDFDA.pdf

5413874 KJDFSXZ.pdf

... etc. etc.

I need to remove the last 7 alpha characters to leave the 7 digits standing as the file name. Through another posted question I was able to find a script that would remove the first X number of digits from the beginning of the file name but I'm having an incredibly difficult time modifying it to remove from the end:

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

Any and all relevant help would be greatly appreciated.

Respectfully,

Upvotes: 2

Views: 9098

Answers (4)

WhooNo
WhooNo

Reputation: 990

A much simpler alternative to PowerShell is using Command Prompt. If your filenames are along the lines of "00001_01.jpg", "00002_01.jpg", "00003_01.jpg", you can use the following command:

ren ?????_0.jpg ?????.jpg

where the number of ? matches the first part of the filename that you want to keep. You can read more about this and other Command Prompt methods of batch renaming files in Windows at this useful website.

Upvotes: 1

js2010
js2010

Reputation: 27418

EDIT: edited to preserve the extension

There's another substring() method that takes 2 args, startIndex and length. https://learn.microsoft.com/en-us/dotnet/api/system.string.substring?view=netframework-4.8

'hithere'.substring

OverloadDefinitions
-------------------
string Substring(int startIndex)
string Substring(int startIndex, int length)

Thus, to delete a total of 8 characters from the right of the basename, including the space:

get-childitem *.pdf | rename-item -newname { $_.basename.substring(0, 
  $_.basename.length-8) + $_.extension } -whatif

What if: Performing the operation "Rename File" on target 
"Item:        /Users/js/1234567890.pdf 
 Destination: /Users/js/12.pdf".

Upvotes: 0

filimonic
filimonic

Reputation: 4634

$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)"}

If file name matches "<FilenameBegin><SevenDigits><Space><Something>.pdf<FilenameEnd>", then rename it to "<SevenDigits>.<KeepExtension>". This uses Regular Expressions with Named Selection groups ( <BeginningDigits> is group name ). Take a note that due to RegExp usage, this is most CPU-taking algorythm, but if you have one-time run or you have little amount of files, there is no sense. Otherwise, if you have many files, I'd recommend adding Where-Object { $_.BaseName.Length -gt 7 } | before if (.. -match ..) to filter out files shorter than 7 symbols before RegExp check to minimize CPU Usage ( string length check is less CPU consumable than RegExp ). Also you can remove \.pdf from RegExp to minimize CPU usage, because you already have this filter in Get-ChildItem

If you strictly need match "<7digits><space><7alpha>.pdf", you should replace RegExp expression with '^(?<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)"}

Alternative: Using string split-join: Rename all files, whose name without extension > 7 symbols to first 7 symbols ( not taking in account if digits or not ), keeping extension. This is idiotic algorythm, because Substring is faster. This just can help learning subarray selection using [x..y]

Please take note that we check string length > 7 before using [x..y] in Where-Object { $_.BaseName.Length -gt 7 }. Otherwise we cat hit error when name is shorter than 7 symbols and we trying to take 7th symbol.


$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)"}

Alternative: Using substring. Rename all files, whose name without extension > 7 symbols to first 7 symbols ( not taking in account if digits or not ), keeping extension.

.Substring(0,7) # 0 - position of first symbol, 7 - how many symbols to take. Please take note that we check string length > 7 before using substring in Where-Object { $_.BaseName.Length -gt 7 }. Otherwise we cat hit error when name is shorter than 7 symbols

Upvotes: 1

tankman175
tankman175

Reputation: 301

You can write a quick bash function for this.

function fileNameShortener() {
    mv "$1" ${1:0:4}
}

This will take the first Argument. which is stored in $1, and create a substring from index 0 to the index 4 characters to the left. This is then used in the move command to move the initial file to the new filename. To Further generalise:

function fileNameShortener2() {
    mv "$1" ${1:$2:$3}
}

This can be used, to give starting point, and length of the Substring as second and third function argument.

fileNameShortener fileName.txt 0 -5 

This sample would remove the last 5 characters from the Filename.

Upvotes: -1

Related Questions