Reputation: 33
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
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
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
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
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