Search code examples
powershellrenaming

Renaming a range from files w/Powershell - from first to third from last hyphen


I have a bunch of csv files I would like to rename with powershell.

from

abc-def-ghi-jkl-mno-pqr-ke-traffic-by-domains-17-Oct-2018_23-49-38-6d73395f476ad09a7506dc00533933b8.csv
abc-def-ghi-jkl-mno-pqr-ke-traffic-by-domains-15-Oct-2018_05-20-36-75eabae7c4123198ff5fe6f4f642449f.csv
abc-def-ghi-jkl-mno-pqr-ke-traffic-by-domains-12-Oct-2018_06-23-58-b13eb8f362c09fbe405458fac8af8f8e.csv

to

abc-17-Oct-2018.csv
abc-15-Oct-2018.csv
abc-12-Oct-2018.csv

I could delete the characters after the underscore (_) with this command

Get-ChildItem -Filter *.csv | Foreach-Object -Process { 
    $NewName = [Regex]::Match($_.Name,"^[^_]*").Value + '.csv'
    $_ | Rename-Item -NewName $NewName}

which leads me to this file name

abc-def-ghi-jkl-mno-pqr-ke-traffic-by-domains-17-Oct-2018.csv

but I am lost at deleting the range of characters from the first hyphen to the third from last hyphen.

I tried this but get an error.

Get-ChildItem -Filter *.csv | Rename-Item -NewName { 
-replace '^[^-]..^[^-]{-3}','^[^-]'}

Could somebody kindly enlighten me how to erase a range? (and possibly combine the former command)


Solution

  • Assuming that all input filenames have the same number of tokens with the same separators in the same positions:

    Get-ChildItem -Filter *.csv | Rename-Item -NewName { 
      (($_.Name -split '[-_]')[0, 10, 11, 12] -join '-') + '.csv' 
    } -WhatIf
    

    -WhatIf previews the renaming operations; remove it to perform actual renaming.

    Splitting the filename into tokens by separators avoids complex regexes; PowerShell's flexible array slicing makes it easy to piece together the target filename from the tokens of interest accessed by their indices.


    That said, if you wanted to do it with -replace and a complex regex:

    Get-ChildItem -Filter *.csv | Rename-Item -NewName { 
      $_.Name -replace '^([^-]+).*?-(\d[^_]+).*', '$1-$2.csv' 
    } -Whatif
    

    This solution doesn't assume a fixed position of the 2nd token to extract - the one before _ - and instead identifies its start by a - followed by a digit (\d).