Skip to content

/flags/powershell/get-childitem-recurse-filter

Get-ChildItem -Recurse -Filter vs -Include: find files in subfolders

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
tool
PowerShell
command
Get-ChildItem
flag
-Recurse (with -Filter, -Include, -Exclude, -Depth)
default
off (only the items directly in -Path are returned)

Get-ChildItem -Path C:\Logs -Recurse -Filter *.log lists every .log file in C:\Logs and all of its subfolders. -Recurse makes the cmdlet walk the whole tree; -Filter narrows the results with a single wildcard pattern that the file system provider applies while it reads the directories, which makes it the fastest option. -Include and -Exclude take several patterns but are applied by PowerShell afterwards, and -Include behaves differently without -Recurse. Aliases are gci, dir and ls.

powershell
Get-ChildItem -Path C:\Logs -Recurse -Filter *.log
Get-ChildItem C:\Logs -Recurse -File -Include *.log, *.txt -Exclude debug*
Get-ChildItem C:\Logs -Recurse -Depth 1 -Filter *.log      # this folder plus one level

-Filter, -Include, -Exclude and -Depth side by side

Checked in Windows PowerShell 5.1 with a small tree (logs\app.log, logs\2026\old.log, logs\2026\10\today.log, logs\2026\10\notes.txt):

powershell
New-Item -ItemType Directory -Path logs\2026\10 -Force | Out-Null
'a' | Set-Content logs\app.log
'b' | Set-Content logs\2026\old.log
'c' | Set-Content logs\2026\10\today.log
'd' | Set-Content logs\2026\10\notes.txt
"-Recurse -Filter *.log:"
Get-ChildItem -Path logs -Recurse -Filter *.log | ForEach-Object { $_.FullName.Substring($PWD.Path.Length + 1) }
"-Recurse -Depth 1 -Filter *.log:"
Get-ChildItem -Path logs -Recurse -Depth 1 -Filter *.log | ForEach-Object { $_.FullName.Substring($PWD.Path.Length + 1) }
"-Include *.log without -Recurse (count):"
(Get-ChildItem -Path logs -Include *.log | Measure-Object).Count
"-Include *.log on logs\*:"
Get-ChildItem -Path logs\* -Include *.log | ForEach-Object Name
"-Recurse -Include *.log,*.txt -Exclude notes*:"
Get-ChildItem -Path logs -Recurse -Include *.log, *.txt -Exclude notes* | Sort-Object Name | ForEach-Object Name
try { Get-ChildItem -Path logs -Filter *.log, *.txt -ErrorAction Stop } catch { "-Filter with two patterns: " + $_.Exception.Message }

Output

-Recurse -Filter *.log:
logs\app.log
logs\2026\old.log
logs\2026\10\today.log
-Recurse -Depth 1 -Filter *.log:
logs\app.log
logs\2026\old.log
-Include *.log without -Recurse (count):
0
-Include *.log on logs\*:
app.log
-Recurse -Include *.log,*.txt -Exclude notes*:
app.log
old.log
today.log
-Filter with two patterns: Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Filter'. Specified method is not supported.
ParameterPatternsApplied byNotes
-Filterone stringthe provider (file system) while readingfastest; passed to the .NET file API, which supports only * and ?
-IncludeseveralPowerShell, after readingneeds -Recurse or a path ending in \*
-ExcludeseveralPowerShell, after readingapplies to item names, not to folders on the way down
-Depth Nnumberrecursion limitPowerShell 5.0+; implies -Recurse
-File / -Directoryswitchprovideronly files or only folders
-Forceswitchprovideralso hidden and system items

Pitfalls

  • -Include without -Recurse. The reference says -Include is effective only when the command includes the contents of an item, such as C:\Windows\*. As the check shows, Get-ChildItem logs -Include *.log returns nothing.
  • -Exclude does not prune folders. -Exclude node_modules drops items named node_modules from the output but still recurses into it. To skip a folder tree, filter on FullName with Where-Object.
  • Access denied in system folders. Recursing through C:\ or a profile hits folders you cannot read; add -ErrorAction SilentlyContinue to suppress those errors, or Stop to fail fast (-ErrorAction Stop).
  • Wrong path. A missing path fails with Cannot find path because it does not exist.
  • Searching inside files. Pipe the result to Select-String to search file contents (Select-String).

FAQ

Why does Get-ChildItem -Include return nothing?

-Include only filters the contents of the path. Without -Recurse, the path must end in a wildcard such as C:\Logs\*; with C:\Logs alone it matches the folder itself, which is not *.log, so the result is empty.

Can -Filter take several patterns?

No. -Filter is a single string, and an array fails with Cannot convert System.Object[] to the type System.String. Use -Include *.log,*.txt with -Recurse, or run Get-ChildItem once per pattern.

How do I get only files or only folders?

Add -File or -Directory (PowerShell 3.0 and later). Get-ChildItem -Recurse -File -Filter *.log returns only files, and -Directory only folders.

Sources