2

I have many files with different names per day. How can I filter them by the date in their name?

For example:

app_20130505.log
app_20130506.log
app_20130507.log
app_20130508.log
app_20130509.log

And my code snippet:

$RetainedDays = 7
$FileNameRegex = "\w+_(\d+)\.\w+"
$ArchiveBoundary = $(Get-Date -Format yyyyMMdd) - $RetainedDays
$ProcessFiles = Get-ChildItem -Path $RootPath -Recurse |
    Where-Object { $_.Name -match $FileNameRegex }

I have regex filter for it : \w+_(\d+)\.\w+, that gives me back the date in $Matches variable, but how can I combine them, and get back the file list, with those files, which older than 7 days?

2
  • I think questions like this are better for stackoverflow then serverfault.
    – tony roth
    May 9, 2013 at 15:28
  • It's possible, but I doesn't know, how can I move the question into stackoverflow. Otherwise it's not a programming question. PowerShell is a script language, what is useful to system administrators, like me and possibly for you.
    – gazsiazasz
    May 9, 2013 at 19:52

3 Answers 3

1

I realize this is a 4 year old question at this point. But I figured I'd add a new answer since there are currently no other up-voted ones.

The way I'd go about this is parsing the date into an actual DateTime object from the file name. Then you can use normal date comparisons rather than string comparisons. The most common way to do this is using a Calculated Property as part of a Select-Object statement. In the example below, we add a calculated property called ParsedDate to the existing output.

$RetainedDays = 7
$FileNameRegex = "\w+_(\d+)\.\w+"
$culture = [System.Globalization.CultureInfo]::InvariantCulture
$ProcessFiles = Get-ChildItem -Path $RootPath -Recurse | 
  Select-Object *,@{
    L='ParsedDate';
    E={ if ($_.Name -match $FileNameRegex) { 
      $strDate = $matches[1];
      [DateTime]::ParseExact($strDate,"yyyyMMdd",$culture)
    }
  }
} | Where { $_.ParsedDate -lt (Get-Date).AddDays(-$RetainedDays) }

The regular expression actually makes things more complicated than they might need to be though. If your files all have the exact same naming pattern of app_<DATE>.log, you can skip the Regex and simplify by letting ParseExact do all the work like this. You just need to escape the literal characters in the format string by surrounding them with single quotes.

$RetainedDays = 7
$culture = [System.Globalization.CultureInfo]::InvariantCulture
$ProcessFiles = Get-ChildItem -Path $RootPath -Recurse | Select FullName,@{
  L='ParsedDate';
  E={ [DateTime]::ParseExact($_.Name,"'app_'yyyyMMdd'.log'",$culture) }
} | Where { $_.ParsedDate -lt (Get-Date).AddDays(-$RetainedDays) }

Technically speaking, you could also do the date parsing inside the Where clause and skip the intermediate Select clause. But I'll leave that as an exercise for the reader.

0

See if this helps get you closer to what you're trying to do.

$RootPath = "C:\temp"
$ProcessFiles = @()
$RetainedDays = 7
$Today = get-date -format yyyyMMdd
$FileNameRegex  = "\w+_(\d+)\.\w+"
foreach ($File in Get-ChildItem -Path $RootPath) {
   $match = [regex]::matches($File, $FileNameRegex )
   $FileNameDate = $match[0].Groups[1].Value
   if (($Today - $FileNameDate) -ge $RetainedDays) { $ProcessFiles += $File }
}
$ProcessFiles
1
  • And I agree with Tony, stackoverflow would be the better choice.
    – Bruce
    May 9, 2013 at 20:29
0

It's not too nice, but works! :)

$RetainedDays = 14

$ArchiveBoundary = (Get-Date).AddDays(-$RetainedDays).ToString('yyyyMMdd')

$ProcessFiles = Get-ChildItem -Path $RootPath -Recurse |
    Where-Object { ($_.BaseName -split '_|\.')[1] -lt $ArchiveBoundary }

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .