MyDaftQuestions
MyDaftQuestions

Reputation: 4701

How to exclude files by part of directory path

I am grabbing all files from a folder recursively.

I want to exclude some directories.

This example works fine, but it only deals with the file extensions

$excluded = @("*.png", "*.svg", "*.jpg")
$files = Get-ChildItem -Path $pth -Recurse -File -Exclude $excluded

One of the paths could contain the directory /debug/, which I don't want to include. However the following has no effect

$excluded = @("*\bin\*", "*\obj\*")
$files = Get-ChildItem -Path $pth -Recurse -File -Exclude $excluded

I am still getting results such as c:\myProj\folder\bin\

I then tried (showing full code)

$excluded = @("*.png", "*.svg", "*.jpg", "*.csproj", "*.sln","*.config","*.dep", "*.gif", "*.license", "*.dll", "*.nupkg", "*.exe", "*.application","*.manifest","*.xml","*.pdb", "*.cache")
$excludedPath = @("*\bin\*", "*\obj\*","*\System.Test\*")
$files = Get-ChildItem -Path $pth -Recurse -File -Exclude $excluded | Where-Object {$_.FullName -notlike $excludedPath} 

Same issue!

PowerShell 5.1

What am I doing wrong?

Upvotes: 1

Views: 1882

Answers (2)

mklement0
mklement0

Reputation: 440536

James C.'s helpful answer offers an elegant solution that uses regex-matching rather than wildcards to match the path portion.

As for:

What am I doing wrong?

  • -Exclude and -Include only ever operate on the last path component; i.e., the file or directory name of the input file at hand.

  • The -like operator only supports one pattern on the RHS (you can, however, use an array of input strings on the LHS to compare to that one pattern)

    • By passing it an array as the RHS, PowerShell implicitly converts it to a string with the array elements concatenated with spaces, resulting in a pattern that doesn't match anything; specifically, the resulting pattern is *\bin\* *\obj\* *\System.Test\*

James C.'s regex-based answer is simpler, but if you did want to use multiple wildcard patterns to match the paths also, the simplest approach would be to use the switch statement with the -Wildcard option:

$files = Get-ChildItem -Path $pth -Recurse -File -Exclude $excluded |
  Where-Object {
    switch -Wildcard $_.FullName {
      *\bin\*         { return $False }
      *\obj\*         { return $False }
      *\System.Test\* { return $False }
      default         { return $True }
    }
  } 

On a side note: Enhancing -Include \ -Exclude to optionally work against full paths is being proposed in this GitHub issue.

Upvotes: 3

henrycarteruk
henrycarteruk

Reputation: 13237

You can exclude folders with regex matching as it saves all the wildcards, in this case | is an 'or' match.

Then use -notmatch to exclude anything that matches the exclusions.

FullName includes the file name, so I'm using DirectoryName so that it doesn't exclude files that match.

$excluded = @("*.txt", "*.csv")
$excludedPath = 'bin|obj|System.Test'

Get-ChildItem -Path $pth -Recurse -File -Exclude $excluded |
  Where-Object {$_.DirectoryName -notmatch $excludedPath} 

Upvotes: 2

Related Questions