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
}
CodePudding user response:
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
}
}