Jeramy
Jeramy

Reputation: 470

Get-ChildItem Where-Object -notlike $array - Is there a way to do this?

I have written a script that will recurse a specified folder and do some analysis on the files within it. I need to exclude specified sub-folders in the analysis. This list of exclusions changes dependent on the base folder being analysed. I have the script working using a long pattern like this:

Get-ChildItem -File -Recurse $source_folder | 
Where-Object {
    $_.FullName -notlike "*\folder_name0\*" -and 
    $_.FullName -notlike "*\folder_name1\*" -and 
    $_.FullName -notlike "*\folder_name2\*" -and 
    $_.FullName -notlike "*\folder_name3\*" -and 
    $_.FullName -notlike "*\folder_name4\*"
}

but this is not very reusable. I would like to be able to store exception lists in .CSVs and call the exception list I need based on the folder set I am analyzing. What I would like to do is something like:

$exception_list = Import-CSV .\exception_list
Get-ChildItem -File -Recurse $source_folder | 
Where-Object {$_.FullName -notlike $exception_list}

but this does not work. I suspect because I can't specify and 'and' or an 'or' between the elements in the array. I did briefly consider trying to create the whole argument on the fly using a foreach($exception in $exception_list){$argument += "$_.FullName -notlike $exception -and"}, but that got silly and complex pretty quickly since you still have to remove the last 'and'.

Is there an efficient way to do this?

Upvotes: 2

Views: 2514

Answers (2)

Max Cascone
Max Cascone

Reputation: 833

I really like @lee_dailey's pattern of creating the regex. An alternative method could be to use -in or -notin to compare collections.

Using Pester:

It 'Filters correctly' {
    $list     = @('fileA', 'file1', 'file2', 'file32')
    $filter   = @('file1', 'file3')
    $expected = @('fileA', 'file2', 'file32')

    $list | Where-Object { $_ -notin $filter} | should -be $expected
  }

Or just plain comparison operators:

$list     = @('fileA', 'file1', 'file2', 'file32')
$filter   = @('file1', 'file3')
$expected = @('fileA', 'file2', 'file32')

$newlist = $list | Where-Object { $_ -notin $filter} 
(Compare-Object $newlist $expected).length -eq 0

> True

Upvotes: 0

Lee_Dailey
Lee_Dailey

Reputation: 7479

this builds an array of partial names to be excluded, and uses that array to build a regex OR for use in a -notmatch test.

$ExcludedDirList = @(
    'PSES-'
    'vscode'
    'Test_'
    )
# regex uses the pipe symbol as the logical "OR"
$RegexExcludedDirList = $ExcludedDirList -join '|'

$Results = Get-ChildItem -Path $env:TEMP -File -Recurse |
    Where-Object {
        $_.DirectoryName -notmatch $RegexExcludedDirList
        }

Upvotes: 5

Related Questions