1

I have a long list of files where various clerks named them inconsistently. They will all have names that begin with a series of numbers representing a 'date' followed by a description. Example

12-16-21 Report.pdf

2-12-22-Report.pdf

03-15-22_report.pdf

I'm looking for a Powershell script or BAT file that can parse these into a consistent format. At least the -date- portion so they sort properly. I don't care about the follow on descriptive text.

2021-12-16 Report.pdf

2022-02-12-Report.pdf

2022-03-15_report.pdf

I tried a Powershell script to rename based on Last Modified Date and found that those dates are not reliable. So I need help to see if there is a regular expression that can be used to parse out the initial numeric chars, reformat as yyyy-MM-dd-whatever, and rename.

$ParsedDate = [datetime]::MinValue;
$Path = "I:\Test";
Get-ChildItem -File -Path $Path -Recurse |
Where-Object { (-not [regex]::IsMatch($_.Name, "^\d{8}_",     [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)) -or (-not [datetime]::TryParseExact($_.Name.Substring(0, 8), "yyyyMMdd", [cultureinfo]::CurrentCulture, [System.Globalization.DateTimeStyles]::None, [ref] $ParsedDate)) } |
    ForEach-Object { Rename-Item -Path ($_.FullName) -NewName "$($_.LastWriteTime.ToString("yyyyMMdd"))_$($_.Name)"; }

So... can someone provide some help with parsing the file name based on those initial numeric chars?

jchwebdev
  • 299

2 Answers2

2

Here is my quick and dirty attempt to do it in Python (works with your example), you can probably port it to Powershell, or just use a similar regex:

import re, os

for file in os.listdir('.'): match = re.search(r'(^\d+).?(\d+).?(\d+)[^A-Za-z0-9](.)', file) if match: m, d, y, s = match.groups() m, d, y = int(m), int(d), int(y) if len(y)>2 else 2000+int(y) new_name = f'{y:04}-{m:02}-{d:02} {s}' os.rename(file, new_name)

1

Here is how to rename the file with Powershell cmdlets

 Get-ChildItem | Where-Object { $_.Name -match "^(\d+)-(\d+)-(\d+)(.+)$" } | foreach-object{
$month = $Matches[1].PadLeft(2,"0")
$day = $Matches[2].PadLeft(2,"0")
$year = "{0:2000}" -f [int]$Matches[3]
$other = $Matches[4]

Rename-Item -Path $_.FullName -NewName ( $year + '-' + $month + '-' + $day + $other )

}