Something broke overnight, the app wrote forty log files, and all you have is an error code like ERR-504. You don't need PowerShell, an editor, or a log tool for the first pass. findstr ships with every Windows install since XP, works in a locked-down cmd.exe, and can tell you which files contain the code, which lines, and whether it's there at all in one command.
This post is the version I actually use: search a whole folder tree, get line numbers, list only file names, avoid the space-separated-words trap, and use the exit code in a batch script.
The one-liner
findstr /s /i /n /l /c:"ERR-504" C:\Logs\*.log
What each switch does:
-
/ssearches the current folder and every subfolder. -
/iignores case, soerr-504andERR-504both match. -
/nprints the line number in front of each hit. -
/ltreats the search text literally (no regex surprises). -
/c:"..."searches for the exact string, spaces included.
Output looks like this, one hit per line, with path:line:text:
C:\Logs\api\2026-10-27.log:1184:2026-10-27 03:12:09 ERR-504 upstream timeout /orders
C:\Logs\api\2026-10-28.log:22:2026-10-28 00:01:44 ERR-504 upstream timeout /orders
C:\Logs\worker\queue.log:907:retry 3/3 failed with ERR-504
That's the whole first-pass triage: you know which service logged it, when, and where to open the file.
Trap #1: spaces mean OR
This is the mistake almost everyone makes once:
findstr "upstream timeout" C:\Logs\api\*.log
That does not search for the phrase upstream timeout. Without /c:, findstr splits the text on spaces and matches lines containing upstream or timeout. You get far more lines than you expected and you don't notice why.
Use /c: whenever the text has a space:
findstr /i /l /c:"upstream timeout" C:\Logs\api\*.log
And when you do want OR, the space behavior is actually handy:
findstr /i /n "ERR-504 ERR-502 ERR-503" C:\Logs\api\*.log
That's every gateway error in one pass.
Trap #2: be explicit about literal vs regex
findstr's regex support is small: ., *, ^, $, [class], [^class], [x-y], \< and \> for word boundaries. There's no +, no |, and no {3} quantifiers. A dot in your search text is a wildcard unless you're in literal mode.
So say what you mean:
:: literal: a dot is just a dot
findstr /s /l /c:"v2.4.1" *.log
:: regex: lines that START with a date like 2026-10-28
findstr /r /n "^2026-10-28" C:\Logs\api\*.log
Adding /l or /r every time costs two characters and removes a whole class of "why does this match?" bugs.
Just tell me which files: /m
When the folder has hundreds of logs, you usually want the list of affected files first, not every line:
findstr /s /i /m /l /c:"ERR-504" C:\Logs\*.log
C:\Logs\api\2026-10-27.log
C:\Logs\api\2026-10-28.log
C:\Logs\worker\queue.log
Count them by piping into find /c /v "", which counts every line it receives:
findstr /s /i /m /l /c:"ERR-504" C:\Logs\*.log | find /c /v ""
Save the hits to a file you can attach to a ticket:
findstr /s /i /n /l /c:"ERR-504" C:\Logs\*.log > C:\Temp\err-504-hits.txt
Hide the noise: /v
/v prints lines that don't match. Combine it with a pipe to strip out the chatter before you search:
type C:\Logs\api\2026-10-28.log | findstr /v /i "DEBUG TRACE" | findstr /i /n "ERR-"
The first findstr throws away DEBUG and TRACE lines, the second finds the errors in what's left. Note that /n now numbers lines in the filtered stream, not the original file, so use the earlier one-liner when you need real line numbers.
Search many codes from a file: /g:
If the on-call runbook lists a dozen error codes, put them in a text file, one per line:
ERR-502
ERR-503
ERR-504
DB-DEADLOCK
Then:
findstr /s /i /n /l /g:C:\Runbook\codes.txt C:\Logs\*.log
Updating the list is now an edit to codes.txt, not to the command.
Use the exit code in a script
findstr sets %ERRORLEVEL% to 0 when it finds at least one match and 1 when it finds none. That makes it a clean yes/no check in a batch file:
@echo off
findstr /s /i /m /l /c:"ERR-504" C:\Logs\*.log >nul
if %errorlevel%==0 (
echo ERR-504 found. Check C:\Logs before closing the incident.
exit /b 1
) else (
echo No ERR-504 in the logs.
)
Or as a quick one-liner at the prompt:
findstr /s /i /m /l /c:"ERR-504" C:\Logs\*.log >nul && echo FOUND || echo clean
Trap #3: a file that "should" match returns nothing
findstr reads files as single-byte text. If a log was written as UTF-16 (for example with > redirection in Windows PowerShell 5.1, whose default output encoding is UTF-16 LE), every character has a null byte next to it and findstr typically finds nothing, with no error.
Quick check: open the file in Notepad and look at the encoding in the status bar. If it says UTF-16, either search it from PowerShell instead:
Select-String -Path C:\Logs\*.log -Pattern 'ERR-504' -SimpleMatch
or fix the writer so it outputs UTF-8. I wrote up the encoding side of this in PowerShell Out-File vs Set-Content: Encoding Is the Real Difference.
Cheat sheet
| Goal | Command |
|---|---|
| Exact phrase, any case, whole tree, with line numbers | findstr /s /i /n /l /c:"text" *.log |
| Any of several words | findstr /i "word1 word2 word3" *.log |
| Only the file names | findstr /s /i /m /l /c:"text" *.log |
| Lines that do NOT match | findstr /v /i "DEBUG" app.log |
| Lines starting with a pattern | findstr /r "^2026-10-28" app.log |
| Many codes from a list | findstr /s /i /l /g:codes.txt *.log |
| Yes/no for a script |
findstr ... >nul, then check %errorlevel% (0 = found) |
Official reference: findstr on Microsoft Learn.
Practice it before the incident
Reading switches is easy. Remembering /c: at 3 AM is the hard part. If you want to build that muscle memory, CMD Master's free interactive Windows command line course runs a real terminal in your browser, with hands-on CMD, PowerShell, and Bash drills and instant feedback, so you can practice searching, filtering, and file operations without touching a production box.
What's the error code you grep for most often? Drop it in the comments.
Top comments (0)