Rename files by the third delimiter from the end of the name

146 views Asked by At

I have a PowerShell code that renaming the files name, and just cutting some letters from the end of the file name. Now I am trying to rename it like this: For example my file name is "a_b_c_d_e_f.txt", so I want to change it to "a_b_c.txt". Any Ideas?

Get-ChildItem 'C:\Users\xxx\Projects\testfiles' -filter *.txt |
  Rename-Item -NewName {$_.name.substring(0,$_.BaseName.length-9) + $_.Extension}
3

There are 3 answers

0
mklement0 On

To complement Paolo's helpful -split answer with a PowerShell (Core) 7+ solution, where the -split operator now accepts negative indices, for splitting from the end of a string:

Get-ChildItem C:\Users\xxx\Projects\testfiles -Filter *.txt | 
  Rename-Item -NewName {
    ($_.BaseName -split '_', -4)[0] + $_.Extension
  } -WhatIf

The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf and re-execute once you're sure the operation will do what you want.

  • -split '_', -4 splits the input file name into substrings by separator _, extracting up to 4 tokens from the end of the string, and returning whatever remains at the front of the input string as the first element.

    • E.g., 'a_b_c_d_e_f' is split into prefix 'a_b_c' and token array @('d', 'e', 'f') (which we're not interested in here).
  • + $_.Extension appends the existing extension to the resulting name, resulting in 'a_b_c.txt'

Note:

  • File names that contain no _ instances are left as-is (no renaming occurs).

  • File names with only 1 to 2 _ instances are renamed to the prefix before their first _; e.g. 'a_b_c.txt' becomes 'a.txt'

  • Individual rename operations may fail, if the new, shortened names result in duplicates.

0
Paolo On

I'd use a helper function for this:

function getNewName($basename, $extension){
  $s = $basename -split "_"
  $n = ($s[0..($s.Length-4)]) -join "_"
  return "$n"+$extension
}

Usage:

> new-item "a_b_c_d_e_f.txt"; 
> Get-ChildItem '.' -filter *.txt | rename-item -NewName {getNewName $_.Basename $_.Extension}

> Get-Item *.txt
a_b_c.txt

the logic of the helper function is to split on _ and join all but the last three elements (in this case, d, e, and f).

0
Theo On

Use regex -replace

Get-ChildItem -Path 'C:\Users\xxx\Projects\testfiles' -Filter '*_*_*_*.txt' -File |
Rename-Item -NewName {'{0}{1}' -f ($_.BaseName -replace '_[^_]+_[^_]+_[^_]+$'), $_.Extension}