Home > OS >  Powershell Folder List Filter
Powershell Folder List Filter

Time:11-09

I have a folder and inside has a list of subfolders/files Folders

  • 2022
  • 20221101
  • 20221103
  • 20221107
  • 20221108
  • test123
  • results
  • test.txt

Using Powershell

  1. How do get the list of folders that are dates.
  2. How do I get the second latest folder (20221107).

This is what I was able to come with so far:

Get-ChildItem "C:\code\Test" -Filter "2022*" | Sort-Object Name -Descending

CodePudding user response:

You can use TryParseExact method from DateTime to parse the folders names and avoid any type of error, this can be combined with Sort-Object and Select-Object to get the 2nd latest. I have added -Directory to output only folders. Also changed your filter to -Filter "2022????" to ensure you're matching folders that start with 2022 and are followed by 4 characters.

$ref = [ref] [datetime]::new(0)

Get-ChildItem "C:\code\Test" -Filter "2022????" -Directory | Sort-Object {
    $result = [datetime]::TryParseExact(
        $_.Name,
        'yyyyMMdd',
        [cultureinfo]::InvariantCulture,
        [Globalization.DateTimeStyles]::AssumeLocal,
        $ref
    )
    if($result) { $ref.Value }
} -Descending | Select-Object -Index 1

If you want to ensure you're matching folders with a date format (because -Filter may be too permissive), you can pipe to Where-Object for additional filtering via regex:

$ref = [ref] [datetime]::new(0)

Get-ChildItem "C:\code\Test" -Filter "2022????" -Directory |
    Where-Object Name -Match '^2022\d{4}$' | Sort-Object {
        # rest of the code here
    } -Descending | Select-Object -Index 1

CodePudding user response:

To provide an alternative to Santiago's helpful answer:

Since the timestamps that your folder names represent sort lexically in a way that is equivalent to their chronological sorting, you may not need to convert them to [datetime] instances, and can sort them as-is.

Get-Item C:\code\Test\* -Include 2022???? |
  Sort-Object Name -Descending |
  Select-Object -Index 1

Note the use of -Include instead of -Filter (which in turn necessitates ending the -Path argument with \* and using Get-Item instead of Get-ChildItem), because the -Filter parameter has legacy quirks that prevent character-exact matching with multiple ? wildcards - see this answer for background information.

  • Unfortunately, as this solution and the linked answer shows, making -Include (and -Exclude) work as intended is tricky as of PowerShell 7.2.x, and requires memorizing non-intuitive rules.

On the plus side, -Include, which (unlike -Filter) uses PowerShell's wildcard expressions, would also allow you to create a more specific pattern, such as -Include 2020[0-1][0-9][0-3][0-9] (which still isn't strict enough to rule out invalid digit combinations, however).

  • Related