Search code examples
powershelldirectorybatch-processing

Powershell move files with timestamp in name into year/month folders


I have a lot of half-hourly files with names in the form A_B_C_YYYYMMDDThhmm_YYYYMMDDThhnn.csv A, B and C are words where YYYY is the year in 4 digits, MM the month in 2 digits, DD the day of the month in 2 digits, hh the hour of the day in 2 dgits, mm the minute in 2 digits, and nn is mm+30 minutes

How can I move these files into folders based on years and months using Powershell?

I have made an attempt based on a previously used script but it is not producing any output for my filename format, presumably because the match string is wrong:

Push-Location 'path/to/files'
Get-ChildItem _*_*.csv |
  Where-Object {$_.BaseName -match '_(\d{4})(\d{2})T(\d{4})_\d{6}T(\d{4})'} | ForEach-Object {
    $TargetDir = "{0}\{1}" -f $Matches[1],$Matches[2]
    if (!(Test-Path $TargetDir)){MD $TargetDir | Out-Null}
    $_ | Move -Destination $TargetDir 
}

Solution

  • At first glance, your regex pattern, as you presumed, was not matching your file names. I have changed the pattern a bit, and using [datetime]::ParsedExact(..) to extract the year and month. Haven't tested this previously but I believe it should work.

    Needles to say, this code is not handling file collision, if there ever is a file with the same name as one of the files being moved to the destination this will fail.

    Push-Location 'path/to/files'
    
    Get-ChildItem -Filter _*_*.csv | ForEach-Object {
        if($_.BaseName -match '(?:\w_){3}(\d{8})T\d{4}_\1T\d{4}') {
            $parsed = [datetime]::ParseExact(
                $Matches[1], 'yyyyMMdd', [cultureinfo]::InvariantCulture
            )
            $folder = '{0:0000}\{1:00}' -f $parsed.Year, $parsed.Month
            $path = Join-Path $PWD.Path -ChildPath $folder
            if(-not (Test-Path $path)) {
                $null = New-Item $path -ItemType Directory
            }
            
            Move-Item -LiteralPath $_.FullName -Destination $path
        }
    }