Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exclude multiple subfolders while using Powershell's method Get-Childitem

What I have

The following working code lists all files from all subfolders where the script is placed.
It includes only certain file types and excludes all files from a certain single folder. So far so good

$fileInclude = @("*.txt", "*.hgr", "*.dat")           
$folderExclude = "C:\folder2"    
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition

gci $scriptPath -recurse -include $fileFilter | Where {$_.FullName -notlike "$folderExclude*"} 

The file structure for my test was as shown

C:.
│   Myscript.ps1
│
├───folder1
│   │   file1.dat
│   │   file1.hgr
│   │   file1.txt
│   │
│   └───folder3
│           file3.dat
│           file3.hgr
│           file3.txt
│
└───folder2
        file3.dat
        file3.hgr
        file3.txt

What I want

Now I want to replace the second line

$folderExclude = "C:\folder2"

with an array. Later there are dozens of paths in it.

$folderExclude = @(
        "C:\folder2", 
        "C:\folder1\folder3"    
        )

Obviously this won't work since -notlike expects a string and not an array of strings.

I can't get my head around how to implement this. I think I need a for-each loop?

like image 646
nixda Avatar asked Nov 07 '13 17:11

nixda


1 Answers

You can also go this route:

$exclude = @('c:\folder2*', 'c:\folder1\folder3'} 
gci | Where {$fn = $_.Fullname; ($exclude | Where {$fn -like $_}).count -eq 0}

And if you are on V4, you can use the handy new common parameter -PipelineVariable:

gci -pv fse | Where {($exclude | Where {$fse.FullName -like $_}).count -eq 0}

Note that this approach has a flaw where if folder1 contains a file called folder3foobar, that file will get excluded. To fix that, you would need to modify the exclude terms to c:\folder1\folder3* and then when you compare against the fse.FullName, you would need to append a backslash if fse was a directory instead of a file.

Here's another approach that works based on -match allowing arrays on the left hand side:

 gci | Where {!($exclude -match [regex]::escape($_.Fullname))}

In this case, if one of the directories does match the $exclude array of terms, then there will be output and that is coerced to true but then gets inverted by the !.

like image 54
Keith Hill Avatar answered Oct 15 '22 10:10

Keith Hill