システム運用やトラブル調査で「複数のログファイルからエラーが出た行だけ集めたい」「サブフォルダ以下にある全ログから特定の文字列を探したい」という場面は頻繁にあります。Windowsのバッチファイルでこれを実現するのがfindstrコマンドです。
findstrは見た目以上に多機能です。/sでサブフォルダを再帰検索、/rで正規表現、複数キーワードのOR検索、マッチしない行の除外(/v)、ファイル名のみ一覧(/m)など、多彩なオプションを組み合わせることで高度なログ解析が可能です。本記事ではオプションの詳細から実務で使えるパターンまで完全に解説します。
- findstrの全オプション(/s・/i・/r・/n・/m・/v・/c・/f)の意味と使い方
- /sでサブフォルダを含む再帰検索をする方法
- 複数キーワードのOR検索・AND相当の検索パターン
- /rで正規表現を使った柔軟な検索(findstrの正規表現の制限も解説)
- /vで除外検索(マッチしない行の抽出)
- for /fと組み合わせたエラー行の集計・件数カウント
- PowerShell Select-Stringとの使い分け判断基準
findstrのオプション一覧
まず主要なオプションを整理します。複数オプションはスラッシュを続けて書けます(例: /isr)。
| オプション | 意味 | 使用例 |
|---|---|---|
/s |
サブフォルダを含めて再帰検索 | findstr /s "ERROR" *.log |
/i |
大文字・小文字を区別しない | findstr /i "error" *.log |
/r |
文字列を正規表現として扱う | findstr /r "[0-9][0-9]:[0-9][0-9]" *.log |
/n |
マッチした行に行番号を表示 | findstr /n "ERROR" app.log |
/m |
マッチしたファイル名のみ表示(行内容を表示しない) | findstr /sm "ERROR" *.log |
/l |
文字列をリテラル(正規表現なし)として扱う(デフォルト) | findstr /l "C:\path" *.log |
/v |
マッチしない行を出力(否定・除外) | findstr /v "DEBUG" *.log |
/c:"文字列" |
スペースを含む文字列で検索 | findstr /c:"login failed" *.log |
/b |
行頭にマッチ | findstr /r /b "[0-9]" *.log |
/e |
行末にマッチ | findstr /r /e "OK$" *.log |
/f:ファイル名 |
検索対象ファイルのリストをファイルから読み込む | findstr /f:files.txt "ERROR" |
/g:ファイル名 |
検索文字列のリストをファイルから読み込む | findstr /g:keywords.txt *.log |
基本:/sでサブフォルダを含めて再帰検索する
/sオプションを使うと指定ディレクトリ以下のすべてのサブフォルダを再帰的に検索します。大量のログファイルが複数フォルダに分散していても1コマンドで横断検索できます。
@echo off rem C:\logs 以下のすべての .log ファイルを再帰検索 findstr /s /i "ERROR" C:\logs\*.log rem 結果をファイルに保存 findstr /s /i "ERROR" C:\logs\*.log > C:\work\error_lines.txt rem 結果とマッチしたファイル名を同時に確認 findstr /s /i /n "ERROR" C:\logs\*.log
C:\logs\app\2026-03-21.log:142:2026-03-21 14:30:01 ERROR Database connection failed C:\logs\app\2026-03-21.log:289:2026-03-21 15:12:44 ERROR Timeout after 30s C:\logs\batch\daily.log:55:2026-03-21 02:00:15 ERROR File not found: input.csv
findstr /sの出力はファイルパス:行番号:行内容の形式(/n使用時)です。ファイル名と行内容がセットで出るためログ調査がしやすくなります。複数キーワードの検索(OR検索・AND検索相当)
OR検索:いずれかの文字列を含む行
findstrはデフォルトで複数の検索文字列をスペース区切りで指定するとOR検索になります。
@echo off rem スペース区切りで複数指定 → OR検索 findstr /s /i "ERROR WARNING CRITICAL" C:\logs\*.log rem /c: オプションを複数使っても OR 検索になる findstr /s /c:"login failed" /c:"access denied" C:\logs\*.log
AND検索相当:すべての文字列を含む行
findstrにはAND検索オプションがありません。パイプでfindstrをチェーンすることで実現します。
@echo off rem パイプで連鎖させると AND 検索になる findstr /s /i "ERROR" C:\logs\*.log | findstr /i "DB_CONNECT" rem 3つのキーワード全部含む行 findstr /s /i "ERROR" C:\logs\*.log | findstr /i "Timeout" | findstr /i "retry"
/sは不要(指定しても無意味)です。また1つ目のfindstrで/nを付けると「ファイル名:行番号:内容」の形式になり、2つ目以降の検索もその文字列全体に対して行われます。/vで除外検索(マッチしない行を抽出する)
/vオプションは指定した文字列を含まない行を出力します。DEBUGや詳細ログを除いてエラーだけを見たいときに使います。
@echo off rem DEBUG行・INFO行を除外する findstr /s /i /v "DEBUG INFO" C:\logs\*.log > C:\work\errors_only.txt rem ERROR含む行から DEBUG を除外(AND NOT 相当) findstr /s /i "ERROR" C:\logs\*.log | findstr /v /i "DEBUG"
@echo off rem 空行とコメント行(# で始まる行)を除外 findstr /v /r "^$" app.log | findstr /v /r "^#"
/rで正規表現を使った柔軟な検索
findstrの正規表現の制限
findstr /rで正規表現が使えますが、標準の正規表現より大幅に機能が制限されています。使える記法は以下のものだけです。
| 記号 | 意味 | 例 |
|---|---|---|
. |
任意の1文字 | ERR.R |
* |
直前の文字の0回以上の繰り返し | ERROR* |
^ |
行頭 | ^2026 |
$ |
行末 | OK$ |
[abc] |
文字クラス(a, b, cのいずれか) | [EW]RROR |
[a-z] |
文字範囲 | [0-9][0-9]:[0-9][0-9] |
\ |
エスケープ | \.(ドットのリテラル) |
+(1回以上)、?(0回または1回)、|(OR)、()(グループ)はfindstrでは動作しません。これらが必要な場合はPowerShellのSelect-Stringを使います。@echo off rem 時刻パターン(HH:MM)を含む行を検索 findstr /s /r /i "[0-2][0-9]:[0-5][0-9]:[0-5][0-9]" C:\logs\*.log rem 行頭が日付で始まる行だけ抽出 findstr /r /b "^2026" C:\logs\app.log rem HTTPステータスコード(3桁数字)を含む行 findstr /r "[0-9][0-9][0-9]" C:\logs\access.log rem ERRORまたはWARNINGを含む行(文字クラスで近似OR) findstr /r /i "^.*[EW][A-Z]*[: ]" C:\logs\*.log
複数ファイルタイプを対象にする
拡張子が混在するフォルダや、ファイルのリストを指定して検索する方法です。
@echo off
rem .log と .txt を対象にする(forで拡張子ごとに呼び出す)
for %%E in (log txt err) do (
findstr /s /i "ERROR" C:\logs\*.%%E >> C:\work\result.txt 2>nul
)
rem または dir /s /b でファイルリストを作成してから /f: で渡す
dir /s /b C:\logs\*.log C:\logs\*.txt > C:\work\filelist.tmp
findstr /i "ERROR" /f:C:\work\filelist.tmp > C:\work\result.txt
del C:\work\filelist.tmp
@echo off rem keywords.txt に1行1キーワードで検索語を書く rem --- keywords.txt の内容 --- rem ERROR rem CRITICAL rem FATAL rem Exception rem ---------------------------- findstr /s /i /g:C:\work\keywords.txt C:\logs\*.log > C:\work\matched.txt echo 検索完了。結果: C:\work\matched.txt
エラー行の件数集計
for /fと組み合わせてマッチした行数をカウントします。ログ監視スクリプトの基本パターンです。
@echo off
setlocal enabledelayedexpansion
set "LOG_DIR=C:\logs"
set "KEYWORD=ERROR"
set "COUNT=0"
for /f "delims=" %%A in ('findstr /s /i "%KEYWORD%" "%LOG_DIR%\*.log"') do (
set /a "COUNT+=1"
)
echo %KEYWORD% 件数: %COUNT% 件
@echo off
setlocal enabledelayedexpansion
set "LOG_DIR=C:\logs"
set /a "CNT_ERR=0, CNT_WARN=0, CNT_INFO=0"
for /f "delims=" %%A in ('findstr /s /i "ERROR" "%LOG_DIR%\*.log"') do set /a "CNT_ERR+=1"
for /f "delims=" %%A in ('findstr /s /i "WARNING" "%LOG_DIR%\*.log"') do set /a "CNT_WARN+=1"
for /f "delims=" %%A in ('findstr /s /i "INFO" "%LOG_DIR%\*.log"') do set /a "CNT_INFO+=1"
echo ===== ログ集計結果 =====
echo ERROR : %CNT_ERR% 件
echo WARNING: %CNT_WARN% 件
echo INFO : %CNT_INFO% 件
rem ERRORが一定数を超えたらアラート
if %CNT_ERR% gtr 10 (
echo [ALERT] ERRORが10件を超えています!
exit /b 1
)
===== ログ集計結果 ===== ERROR : 23 件 WARNING: 87 件 INFO : 1542 件 [ALERT] ERRORが10件を超えています!
マッチしたファイルの一覧取得(/m)
/mオプションはマッチした行の内容ではなくファイル名だけを出力します。「どのファイルにエラーが含まれているか」の一覧取得に便利です。
@echo off
rem マッチしたファイル名だけ表示
findstr /s /m /i "ERROR" C:\logs\*.log
rem 件数もカウント
set "FILE_COUNT=0"
for /f "delims=" %%F in ('findstr /s /m /i "ERROR" C:\logs\*.log') do (
echo エラーあり: %%F
set /a "FILE_COUNT+=1"
)
echo エラーを含むファイル数: %FILE_COUNT% 件
エラーあり: C:\logs\app\2026-03-19.log エラーあり: C:\logs\app\2026-03-21.log エラーあり: C:\logs\batch\daily.log エラーを含むファイル数: 3 件
実用テンプレート:毎日のエラーログ監視スクリプト
タスクスケジューラと組み合わせて毎日ログを検査し、エラーがあれば結果ファイルに書き出す監視テンプレートです。
@echo off
setlocal enabledelayedexpansion
set "LOG_DIR=C:\logs"
set "REPORT_DIR=C:\reports"
set "TODAY=%DATE:~0,4%%DATE:~5,2%%DATE:~8,2%"
set "REPORT=%REPORT_DIR%\error_report_%TODAY%.txt"
set "KEYWORDS_FILE=C:\scripts\keywords.txt"
if not exist "%REPORT_DIR%" mkdir "%REPORT_DIR%"
echo ===== エラーログ検査レポート %DATE% %TIME% ===== > "%REPORT%"
echo 対象ディレクトリ: %LOG_DIR% >> "%REPORT%"
echo. >> "%REPORT%"
rem ----- ERRORの集計 -----
set /a "CNT=0"
for /f "delims=" %%A in ('findstr /s /i "ERROR CRITICAL FATAL" "%LOG_DIR%\*.log" 2^>nul') do (
echo %%A >> "%REPORT%"
set /a "CNT+=1"
)
echo. >> "%REPORT%"
echo ===== 検出件数: !CNT! 件 ===== >> "%REPORT%"
if !CNT! gtr 0 (
echo [ALERT] %TODAY%: エラー !CNT! 件を検出 → %REPORT%
exit /b 1
) else (
echo [OK] %TODAY%: エラーなし
exit /b 0
)
PowerShell Select-Stringとの比較・使い分け
複雑な検索や文字コードが絡む場合はPowerShellのSelect-String(sls)が強力です。
| 比較項目 | findstr | PowerShell Select-String |
|---|---|---|
| 速度 | ◎ 高速 | ○ やや遅い(大量ファイルで差が出る) |
| 正規表現 | △ 限定的(+?|()なし) | ◎ Perlベースの正規表現がフル利用可能 |
| 文字コード(UTF-8等) | △ SJISのみ確実(UTF-8 BOMなしは化ける) | ◎ エンコーディング指定可能(-Encoding) |
| AND検索 | △ パイプで代替 | ◎ -Pattern を複数指定・Where-Objectで柔軟 |
| バッチとの統合 | ◎ ネイティブに使える | ○ for /fで結果を受け取れる |
| コンテキスト表示 | × 前後の行表示なし | ◎ -Context 前後N行を表示 |
@echo off
rem findstrと同等の再帰検索(PowerShell版)
powershell -NoProfile -Command ^
"Get-ChildItem C:\logs -Recurse -Filter *.log | ^
Select-String -Pattern 'ERROR|WARNING' -AllMatches | ^
Select-Object Filename,LineNumber,Line | ^
Format-Table -AutoSize"
よくある落とし穴と対処法
落とし穴①:UTF-8(BOMなし)ファイルは文字化けする
findstrはSJIS(CP932)を前提に動作します。UTF-8 BOMなしのログファイルは日本語が文字化けして検索がうまくいかないことがあります。
@echo off
rem UTF-8ファイルはPowerShellで検索する
for /f "usebackq delims=" %%A in (`powershell -NoProfile -Command ^"
Get-ChildItem C:\logs -Recurse -Filter *.log |
Select-String -Pattern 'ERROR' -Encoding UTF8 |
ForEach-Object { $_.Path + ':' + $_.LineNumber + ':' + $_.Line }
^"`) do echo %%A
落とし穴②:スペースを含む検索文字列は /c: が必要
rem NG: スペースで区切られてOR検索になる findstr /s "login failed" C:\logs\*.log rem → "login" OR "failed" を検索してしまう rem OK: /c: オプションでスペースごとリテラル検索 findstr /s /c:"login failed" C:\logs\*.log
落とし穴③:for /f 内のパイプは ^ でエスケープ
rem NG: | が先に解釈されてエラー
for /f %%A in ('findstr /s "ERROR" *.log | findstr "DB"') do echo %%A
rem OK: ^ でエスケープ
for /f "delims=" %%A in ('findstr /s "ERROR" "C:\logs\*.log" ^| findstr "DB"') do echo %%A
落とし穴④:/s はディレクトリを指定するときにパスが必要
rem NG: ディレクトリ名だけ(ファイルパターンが必要) findstr /s "ERROR" C:\logs\ rem OK: ワイルドカード付きで指定 findstr /s "ERROR" C:\logs\*.log findstr /s "ERROR" C:\logs\*.*
関連記事
- 【bat】バッチファイルでログを解析・集計する完全ガイド(行カウント・キーワード集計・エラー抽出・時系列分析)
- 【bat】バッチファイルでログ出力する方法完全ガイド(ログファイルの作成・タイムスタンプ・ローテーション)
- 【bat】外部コマンドの結果を変数に格納する方法完全ガイド(for /fでfindstr結果を変数に取り込む方法)
- 【bat】typeコマンド完全ガイド(ファイル内容の表示・連結・findstrとの組み合わせ)
よくある質問
findstr /s /m "キーワード" *.logでキーワードを含むファイル名を取得し、全ファイルのリストとの差分を取る方法があります。またはfindstr /v /m "キーワード"は使えません(/vと/mの組み合わせは期待通りに動作しない場合があります)。この用途はPowerShellのGet-ChildItem | Where-Object { -not (Select-String ...) }の方が確実です。findstrにはコンテキスト表示機能がありません。マッチした行の前後N行を表示したい場合はPowerShellのSelect-String -Context 前,後を使います。例: Get-ChildItem *.log | Select-String "ERROR" -Context 2,2でマッチ行の前2行・後2行を表示できます。Select-String -Encoding UTF8を使う、③英数字のみのキーワードで検索する(ASCII文字はSJIS/UTF-8共通のため影響を受けない)の3つです。/mオプションでファイル名だけ取得(行内容の出力をしないので高速)、②検索対象のファイルパターンを絞り込む(全拡張子*.*より*.logの方が速い)、③期間で絞ったファイルのリストを事前に作成して/f:で渡す、④PowerShellのSelect-Stringはパイプラインで並列処理される場合があり大量ファイルで有利なこともあります。findstrの正規表現に+はありません。代替として.と*を組み合わせて近似表現を作ります(例: ERR.*でERRに何かが続くパターン)。ただし完全な+の動作にはなりません。本格的な正規表現が必要な場合はPowerShellのSelect-Stringを使ってください。PowerShellは.NETの正規表現エンジンを使うため、+・?・|・()・\d・\wなど標準的な記法がすべて使えます。

