gonzo
gonzo

Reputation: 5

Get list of files with a specific date range

Windows 10 x64 1709
PowerShell 5.1

I have a PowerShell script that recursively lists all files in a directory (and sub-directories) and outputs the list to a text file. I want now to get the files with LastWriteTime within a specific date range. I found the following as an example in other questions/sites, which should work:

(Get-ChildItem 'C:\path\to\files\raw\*.xml' -Recurse).FullName | Where-Object {
    $_.LastWriteTime -ge '01/01/2019 00:00:00' -and
    $_.LastWriteTime -le '22/04/2019 00:00:00'
} > 'C:\path\to\files\filelist.txt'

(date is in dd/MM/YYYY in my system, but I tried other formats as well, just in case)

At first I thought it was an issue related to the date/time format, and I spent several hours banging my head and trying all kinds of conversions. I also tried using Where instead of Where-Object, same issue.

I finally thought of trying something simpler: running each condition separately. And lo-and-behold, here's the deal.

If I run the -le

(Get-ChildItem 'C:\path\to\files\raw\*.xml' -Recurse).FullName |
    where LastWriteTime -le '22/04/2018 01:00:00'

I get a list of files.

If I run the -ge

(Get-ChildItem 'C:\path\to\files\raw\*.xml' -Recurse).FullName |
    where LastWriteTime -ge '01/01/2019 00:00:00'

the list is empty (no errors either).

The following, however, does work:

(Get-ChildItem 'C:\path\to\files\raw\*.xml' -Recurse).FullName |
    where LastWriteTime -ge $Today

I looked for documentation on the -ge parameter; tried it in lower/uppercase... no go.

Am I missing something obvious? Is -ge broken?

PS: I tried changing LastWriteTime with CreationTime and the issue persists (not that it matters, but just mentioning it).

Upvotes: 0

Views: 11003

Answers (1)

StephenP
StephenP

Reputation: 4081

First, you aren't passing file objects down the pipe, you are passing strings by using the .FullName property. These filenames are just filenames, they don't have a LastWriteTime property. Change your script to simply pass the file object.

Get-ChildItem 'C:\path\to\files\raw\*.xml' -Recurse |

Second, convert your comparison of dates to datetime objects. Otherwise you are comparing DateTime objects from LastWriteTime to System.String. Powershell will attempt to convert but gets it wrong sometimes due to locale formatting differences. For example: Get-Date '22/04/2019 01:00:00' errors for me. I would parse the date strings with the DateTime.ParseExact method. You may need to change the CultureInfo for your location.

$upperBound = [datetime]::ParseExact('22/04/2019 01:00:00',
                                     'dd/MM/yyyy hh:mm:ss',
                                     [Cultureinfo]::InvariantCulture)
$lowerBound = [datetime]::ParseExact('01/01/2019 01:00:00',
                                     'dd/MM/yyyy hh:mm:ss',
                                      [Cultureinfo]::InvariantCulture)

Get-ChildItem 'C:\path\to\files\raw\*.xml' -Recurse | Where-Object {
    $_.LastWriteTime -ge $lowerBound -and $_.LastWriteTime -le $upperBound
}  | Select-Object -ExpandProperty FullName

Upvotes: 3

Related Questions