PowerShell Find Files by Name or Extension Recursively

You know the file is somewhere on the server. It’s a .bak file, or maybe you remember part of the name. File Explorer will grind through directories for minutes — PowerShell finds it in seconds and returns a real object you can act on. This guide covers every approach to PowerShell find files recursively: by extension, partial name, date, size, and across multiple drives, with examples you can use immediately.
Find All Files by Extension
The fastest approach for extension-based search uses -Filter, which filters at the OS level:
# Find all .log files recursively
Get-ChildItem -Path 'C:\' -Filter '*.log' -Recurse -ErrorAction SilentlyContinue
# Find all PowerShell scripts
Get-ChildItem -Path 'C:\Scripts' -Filter '*.ps1' -Recurse
# Get just the full paths
Get-ChildItem -Path 'C:\' -Filter '*.bak' -Recurse -File -ErrorAction SilentlyContinue |
Select-Object FullName, Length, LastWriteTime
FullName Length LastWriteTime
-------- ------ -------------
C:\Databases\prod\backup.bak 5368709120 4/30/2026 2:00 AM
C:\Databases\dev\dev-backup.bak 536870912 5/1/2026 11:00 PM
Always add -ErrorAction SilentlyContinue when searching from a drive root — access-denied errors on system folders will stop the search without it.
Find by Partial Name with Wildcards
When you know part of the filename, use wildcards in -Filter or -Name:
# Find files with 'deploy' anywhere in the name
Get-ChildItem -Path 'C:\Projects' -Filter '*deploy*' -Recurse
# Find files starting with a date pattern
Get-ChildItem -Path 'C:\Logs' -Filter '2026-05-*' -Recurse
# Case-insensitive wildcard — -Filter is already case-insensitive
Get-ChildItem 'C:\' -Filter '*backup*' -Recurse -File -ErrorAction SilentlyContinue |
Select-Object -First 20 FullName
FullName
--------
C:\Backups\system-backup-2026-05-01.zip
C:\SQL\backup\full-backup.bak
C:\Scripts\run-backup.ps1
Search in Multiple Drives
Search across all drives by iterating the drive list:
# Search all local drives
$localDrives = Get-PSDrive -PSProvider FileSystem | Where-Object { $_.Used -ne $null }
foreach ($drive in $localDrives) {
Write-Output "Searching $($drive.Name):..."
Get-ChildItem "$($drive.Name):\" -Filter '*.mdf' -Recurse -File -ErrorAction SilentlyContinue |
Select-Object FullName, @{ Name='SizeGB'; Expression={ [math]::Round($_.Length/1GB,2) } }
}
# One-liner version
Get-PSDrive -PSProvider FileSystem |
ForEach-Object { Get-ChildItem "$($_.Name):\" -Filter '*.iso' -Recurse -File -ErrorAction SilentlyContinue }
Searching C:...
Searching D:...
FullName SizeGB
-------- ------
C:\SQL\Data\Production.mdf 4.82
D:\Databases\Archive\Old.mdf 1.23
Filter by Date Modified
Find files modified within a specific time window:
# Files modified in the last 24 hours
$since = (Get-Date).AddHours(-24)
Get-ChildItem 'C:\Logs' -Recurse -File |
Where-Object { $_.LastWriteTime -gt $since } |
Select-Object FullName, LastWriteTime
# Files older than 90 days (cleanup candidates)
$cutoff = (Get-Date).AddDays(-90)
Get-ChildItem 'C:\Logs\Archive' -Recurse -File |
Where-Object { $_.LastWriteTime -lt $cutoff } |
Select-Object FullName, LastWriteTime, Length
# Files created today
$today = (Get-Date).Date
Get-ChildItem 'C:\Downloads' -File |
Where-Object { $_.CreationTime -ge $today }
FullName LastWriteTime
-------- -------------
C:\Logs\app.log 5/4/2026 9:15 AM
C:\Logs\error.log 5/4/2026 8:01 AM
Find Largest Files
The classic disk space investigation — find the biggest files consuming space:
# Top 20 largest files on C: drive
Get-ChildItem -Path 'C:\' -Recurse -File -ErrorAction SilentlyContinue |
Sort-Object Length -Descending |
Select-Object -First 20 FullName,
@{ Name='SizeGB'; Expression={ [math]::Round($_.Length/1GB,3) } } |
Format-Table -AutoSize
# Files larger than 1GB specifically
Get-ChildItem -Path 'C:\' -Recurse -File -ErrorAction SilentlyContinue |
Where-Object { $_.Length -gt 1GB } |
Select-Object FullName, @{ Name='SizeGB'; Expression={ [math]::Round($_.Length/1GB,2) } } |
Sort-Object SizeGB -Descending
FullName SizeGB
-------- ------
C:\Windows\Installer\archive.msi 5.120
C:\Users\Alice\Videos\vacation.mp4 3.847
C:\Databases\prod\Production.mdf 4.820
Export Search Results
Get-ChildItem -Path 'C:\' -Filter '*.log' -Recurse -File -ErrorAction SilentlyContinue |
Select-Object FullName, Name, Length, LastWriteTime,
@{ Name='SizeMB'; Expression={ [math]::Round($_.Length/1MB,2) } } |
Sort-Object Length -Descending |
Export-Csv 'C:\Reports\log-file-inventory.csv' -NoTypeInformation
Write-Output "Inventory saved to C:\Reports\log-file-inventory.csv"
Common Errors and Fixes
-
-Filter only accepts one pattern; use -Include for multiple:
Get-ChildItem -Filter '*.log','*.txt'silently uses only the first pattern. For multiple extensions, use-Include @('*.log','*.txt') -Recurse, or pipe toWhere-Object { $_.Extension -in @('.log','.txt') }. -
Access denied on system folders stops recursion: Without
-ErrorAction SilentlyContinue, the first inaccessible folder terminates the entire search. Always include this flag for any recursive search starting at a drive root or system path.
Related Cmdlets / See Also
Wrapping Up
PowerShell file finding is faster and more capable than File Explorer. Use -Filter for single-extension searches, -Include for multiple extensions, and Where-Object for date and size filters. Always add -ErrorAction SilentlyContinue when recursing from drive roots. Export results to CSV for documentation. Your next step: find all files larger than 500MB on your server’s data drive and export the list for cleanup review.


