How to Search a String in Multiple Files and Return the File Names in PowerShell

To find every file under a folder that contains a string, and print only the file names, run this in PowerShell:

Get-ChildItem -Path C:\Projects -Recurse -File | Select-String -Pattern "Timeout" -List | Select-Object -ExpandProperty Path

Get-ChildItem -Recurse -File lists every file in C:\Projects and its subfolders. Select-String reads each one and reports lines that match the pattern. -List stops at the first match per file, so each file appears once. Select-Object -ExpandProperty Path prints the full path as plain text instead of the match object.

Why Get-ChildItem does the recursion

Select-String has no -Recurse parameter. Its -Path parameter accepts wildcards, so Select-String -Path C:\Logs\*.log -Pattern "Error" searches one folder, but it will not descend into subfolders. For a recursive search, Get-ChildItem walks the tree and pipes the files in.

When one folder is enough, the shorter form works:

Select-String -Path C:\Logs\*.log -Pattern "Error" -List | Select-Object -ExpandProperty Path

Return only the file names

Select-String returns MatchInfo objects with Path, Filename, LineNumber and Line properties. Pick the property you want.

$files = Get-ChildItem -Path C:\Projects -Recurse -File # Full paths, one per file $files | Select-String -Pattern "Timeout" -List | Select-Object -ExpandProperty Path # File names without the folder $files | Select-String -Pattern "Timeout" -List | Select-Object -ExpandProperty Filename # Every matching line, then collapse to unique paths $files | Select-String -Pattern "Timeout" | Select-Object -ExpandProperty Path -Unique # Number of matching lines per file $files | Select-String -Pattern "Timeout" | Group-Object Path | Select-Object Name, Count

To save the list, pipe it to Set-Content:

$files | Select-String -Pattern "Timeout" -List | Select-Object -ExpandProperty Path | Set-Content C:\Temp\matches.txt

Useful variants

NeedAddNote
Literal text, not a regex-SimpleMatch-Pattern is a regular expression by default, so . and ( have special meaning
Case-sensitive match-CaseSensitiveThe default ignores case
Only some file types-Include *.log,*.txt on Get-ChildItem-Include needs -Recurse or a wildcard in the path
Skip a folderWhere-Object FullName -notlike "*\node_modules\*" before Select-String-Exclude matches names, not full paths
Just true or false-QuietOne boolean per input; useful inside an if
Lines around each match-Context 2,2Two lines before and two after
Files in another encoding-Encoding UTF8 or UnicodeSet it when matches are missed in files that are not UTF-8

Two of these deserve a sentence. Searching for config.json without -SimpleMatch also matches configXjson, because . matches any character. And -NotMatch does not list files that lack the string; it lists lines that lack it. For files without the string, filter the other way:

$files | Where-Object { -not ($_ | Select-String -Pattern "Timeout" -Quiet) } | Select-Object -ExpandProperty FullName

Find a file by name

Finding a file by its name needs only Get-ChildItem; no content search is involved.

# Files whose name contains "config", anywhere under C:\Projects Get-ChildItem -Path C:\Projects -Recurse -File -Filter "*config*" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName # One exact name, searched from the drive root Get-ChildItem -Path C:\ -Recurse -File -Filter "web.config" -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName

-Filter is applied by the file system provider before any objects are created, so it is faster than -Include or a later Where-Object. -ErrorAction SilentlyContinue hides the access-denied errors that a scan from a drive root produces.

The two ideas combine. To search inside only the files whose names match, filter by name first and then read them:

Get-ChildItem -Path C:\Projects -Recurse -File -Filter "*.config" | Select-String -Pattern "connectionString" -List | Select-Object -ExpandProperty Path

On a large tree this is much faster than reading every file, because Select-String opens only the files that pass the filter.

Key Takeaways

TAGS
Coding Interview
CONTRIBUTOR
Arslan Ahmad
Arslan Ahmad
ex-FAANG engineering manager and author or Grokking series.

GET YOUR FREE

Coding Questions Catalog

Design Gurus Newsletter - Latest from our Blog
Boost your coding skills with our essential coding questions catalog.
Take a step towards a better tech career now!
Explore Answers
How many days to master LeetCode?
What is the entry level package of Cisco?
What is basic of testing?
How many questions are asked in a behavioral interview?
What is MIT portfolio?
What Is the Anduril Interview Process Like? (Round by Round)
Anduril runs a recruiter screen, a technical phone screen, and a four-session final round, and candidates report three to four weeks from first call to offer.
Related Courses
New
Grokking the AI System Design Interview course cover
Grokking the AI System Design Interview
Learn to design AI systems the way interviewers expect: classic ML products, LLM and RAG architectures, and agentic systems, all through the lens of the system design interview.
4.6
(3,192 learners)
Discounted price for Your Region

$99

Grokking the Coding Interview: Patterns for Coding Questions course cover
Grokking the Coding Interview: Patterns for Coding Questions
The 24 essential patterns behind every coding interview question. Available in Java, Python, JavaScript, C++, C#, and Go. The most comprehensive coding interview course with 543 lessons. A smarter alternative to grinding LeetCode.
4.6
Discounted price for Your Region

$197

Grokking Modern AI Fundamentals course cover
Grokking Modern AI Fundamentals
Master the fundamentals of AI today to lead the tech revolution of tomorrow.
4.1
Discounted price for Your Region

$72

Design Gurus logo
One-Stop Portal For Tech Interviews.
About Us
Our Team
Careers
Partners
Contact Us
Become Affiliate
Copyright © 2026 Design Gurus, LLC. All rights reserved.