How can I exclude multiple folders using Get-ChildItem -exclude?
My KISS approach to skip some folders is chaining Get-ChildItem
calls. This excludes root level folders but not deeper level folders if that is what you want.
Get-ChildItem -Exclude folder1,folder2 | Get-ChildItem -Recurse | ...
- Start excluding folders you don't want
- Then do the recursive search with non desired folders excluded.
What I like from this approach is that it is simple and easy to remember. If you don't want to mix folders and files in the first search a filter would be needed.
I'd do it like this:
Get-ChildItem -Path $folder -r | ? { $_.PsIsContainer -and $_.FullName -notmatch 'archive' }
Note that -notmatch
accepts a Regular Expression:
https://docs.microsoft.com/powershell/module/microsoft.powershell.core/where-object#parameters
I apologize if this answer seems like duplication of previous answers. I just wanted to show an updated (tested through POSH 5.0) way of solving this. The previous answers were pre-3.0 and not as efficient as modern solutions.
The documentation isn't clear on this, but Get-ChildItem -Recurse -Exclude
only matches exclusion on the leaf (Split-Path $_.FullName -Leaf
), not the parent path (Split-Path $_.FullName -Parent
). Matching the exclusion will just remove the item with the matching leaf; Get-ChildItem
will still recurse into that leaf.
In POSH 1.0 or 2.0
Get-ChildItem -Path $folder -Recurse | ? { $_.PsIsContainer -and $_.FullName -inotmatch 'archive' }
Note: Same answer as @CB.
In POSH 3.0+
Get-ChildItem -Path $folder -Directory -Recurse | ? { $_.FullName -inotmatch 'archive' }
Note: Updated answer from @CB.
Multiple Excludes
This specifically targets directories while excluding leafs with the Exclude
parameter, and parents with the ilike
(case-insensitive like) comparison:
#Requires -Version 3.0[string[]]$Paths = @('C:\Temp', 'D:\Temp')[string[]]$Excludes = @('*archive*', '*Archive*', '*ARCHIVE*', '*archival*')$files = Get-ChildItem $Paths -Directory -Recurse -Exclude $Excludes | %{ $allowed = $true foreach ($exclude in $Excludes) { if ((Split-Path $_.FullName -Parent) -ilike $exclude) { $allowed = $false break } } if ($allowed) { $_ }}
Note: If you want your $Excludes
to be case-sensitive, there are two steps:
- Remove the
Exclude
parameter fromGet-ChildItem
. - Change the first
if
condition to:if ($_.FullName -clike $exclude) {
Note: This code has redundancy that I would never implement in production. You should simplify this quite a bit to fit your exact needs. It serves well as a verbose example.