1

I want to get all .JPG files in current and all sub-directories where the directory name is in the YYYY-MM-DD format. i.e.

D:\Pictures\2018-01-01\DSC_0001.JPG <- yes, include
D:\Pictures\2018\01\DSC_0001.JPG <- do not include

This is what I've tried, no luck.

$testFiles = Get-ChildItem -Path $srcFolder -Filter *.JPG | ? { (Split-Path (Split-Path $_ -Parent) -Leaf) -match '^\d{4}-\d{2}-\d{2}$' }

crichavin
  • 4,672
  • 10
  • 50
  • 95
  • I know that it's not obvious that this question is a duplicate of the linked one, but it comes down to (a) PowerShell cmdlets regrettably binding file/directory-path arguments as _strings_, not filesystem-info object, and (b) filesystem-info objects stringifying _inconsistently_. – mklement0 Feb 05 '19 at 02:42

3 Answers3

2

You nearly had it.

$testFiles = Get-ChildItem -Path $srcFolder -Recurse -Filter *.JPG 
| Where-Object { (Split-Path (Split-Path $_.FullName -Parent) -Leaf) -match '^\d{4}-\d{2}-\d{2}$' }

You need to set the path by using $_.Fullname as $_ passes the entire object.

Drew
  • 3,814
  • 2
  • 9
  • 28
  • 1
    It's an effective solution, but to be clear: passing an _object_ should be an _advantage_ in PowerShell, not a liability: all cmdlets in PowerShell _should_ accept filesystem-info _objects_ in lieu of path strings _robustly_, whereas, regrettably, (a) they accept path _strings_ only, and (b) [the inconsistent manner in which filesystem-info objects _stringify_](https://stackoverflow.com/a/53400031/45375) is the root of the problem. See also: https://github.com/PowerShell/PowerShell/issues/6057 – mklement0 Feb 05 '19 at 02:49
1

here is a slightly different way to get the file list. [grin] it tests against the .Directory property of the files.

_[edit - the original version matched against the entire dir name AND failed to get dir names with ONLY the date pattern.]_

$SourceDir = $env:temp
$Filter = '*.log'
# this pattern will give embedded date patterns
#$DirPattern = '\d{4}-\d{2}-\d{2}'
# this pattern gives ONLY a date pattern
$DirPattern = '^\d{4}-\d{2}-\d{2}$'

$GCI_Params = @{
     LiteralPath = $SourceDir
     Filter = $Filter
     File = $True
     Recurse = $True
    }
$FileList = Get-ChildItem @GCI_Params |
    # this matches against the entire directory
    #Where-Object {$_.Directory -match $DirPattern}
    # this one correctly filters against only the parent dir
    Where-Object {(Split-Path -Path $_.DirectoryName -Leaf) -match $DirPattern}

$FileList.Count

on my system, at this time, it returns ~~67~~ 54 as the count of matching files.

Lee_Dailey
  • 7,292
  • 2
  • 22
  • 26
  • This works, but it searches the full path for the pattern, I only want it to search file's parent directory only, not the full path. I also only want it to find folders that are just `YYYY-MM-DD`, so `YYYY-MM-DD Chucks BDay Party` would not match. I think that part is just adjusting the pattern regex, but the parent directory name only search will not work with $_.Directory, hence the nested `Split-Path` solution. If there is a better way to get the parent directory name only, and not the full path, I'd greatly welcome it :) – crichavin Feb 05 '19 at 18:44
  • @ChadRichardson - arg! for some reason i thot that this was only seeing the parent dir name instead of the entire dir name. [*blush*] you are correct that fitting your requirements would need a split of some kind AND a delimiter test. do you think i should modify the answer to include those? – Lee_Dailey Feb 05 '19 at 19:09
  • thanks Lee, the other answer I've already accepted and it works, so you don't need to waste any more time on this, but I appreciated your input. – crichavin Feb 05 '19 at 19:14
  • @ChadRichardson - i think i will fix it - with notes - just to avoid confusing anyone who looks into it. thanks for pointing out the glitches! [*grin*] – Lee_Dailey Feb 05 '19 at 19:15
0

I'm not sure what you're doing with the nested split-path, but it didn't work in my test.

This worked, and may serve your needs:

gci *.jpg -Recurse | ? { $_.FullName -match '\\\d{4}-\d{2}-\d{2}\\' }`
Rich Moss
  • 2,195
  • 1
  • 13
  • 18