【bat】findstrで複数ログファイルを一括検索する方法完全ガイド|/s再帰・正規表現・OR/AND検索・除外・エラー集計・PowerShell比較まで徹底解説

【bat】複数のログファイルを一括で検索する方法(findstr /s) bat

システム運用やトラブル調査で「複数のログファイルからエラーが出た行だけ集めたい」「サブフォルダ以下にある全ログから特定の文字列を探したい」という場面は頻繁にあります。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コマンドで横断検索できます。

サブフォルダを含めてERRORを含む行を検索
@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検索になります。

OR検索:ERRORまたはWARNINGを含む行
@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をチェーンすることで実現します。

AND検索:ERRORかつDB_CONNECTを含む行
@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 が無効: パイプで受け取ったデータはファイルではなく標準入力になるため、2つ目以降のfindstrに/sは不要(指定しても無意味)です。また1つ目のfindstrで/nを付けると「ファイル名:行番号:内容」の形式になり、2つ目以降の検索もその文字列全体に対して行われます。

/vで除外検索(マッチしない行を抽出する)

/vオプションは指定した文字列を含まない行を出力します。DEBUGや詳細ログを除いてエラーだけを見たいときに使います。

DEBUGとINFOを除いてERROR系だけ抽出
@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
/g:オプションで複数キーワードをファイルから読み込む
@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と組み合わせてマッチした行数をカウントします。ログ監視スクリプトの基本パターンです。

ERRORが含まれる行数を集計する
@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オプションはマッチした行の内容ではなくファイル名だけを出力します。「どのファイルにエラーが含まれているか」の一覧取得に便利です。

ERRORを含むファイル名の一覧を取得
@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 件

実用テンプレート:毎日のエラーログ監視スクリプト

タスクスケジューラと組み合わせて毎日ログを検査し、エラーがあれば結果ファイルに書き出す監視テンプレートです。

daily_log_check.bat(日次エラー監視テンプレート)
@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-Stringsls)が強力です。

比較項目 findstr PowerShell Select-String
速度 ◎ 高速 ○ やや遅い(大量ファイルで差が出る)
正規表現 △ 限定的(+?|()なし) ◎ Perlベースの正規表現がフル利用可能
文字コード(UTF-8等) △ SJISのみ確実(UTF-8 BOMなしは化ける) ◎ エンコーディング指定可能(-Encoding)
AND検索 △ パイプで代替 ◎ -Pattern を複数指定・Where-Objectで柔軟
バッチとの統合 ◎ ネイティブに使える ○ for /fで結果を受け取れる
コンテキスト表示 × 前後の行表示なし ◎ -Context 前後N行を表示
PowerShell Select-Stringでの同等検索
@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"
使い分けの基準: バッチスクリプト内でシンプルなキーワード検索をするならfindstr、正規表現(+・?・|等)が必要・UTF-8ファイルを扱う・前後の行も見たいならPowerShell Select-Stringを選ぶと効率的です。

よくある落とし穴と対処法

落とし穴①:UTF-8(BOMなし)ファイルは文字化けする

findstrはSJIS(CP932)を前提に動作します。UTF-8 BOMなしのログファイルは日本語が文字化けして検索がうまくいかないことがあります。

対処:PowerShellでUTF-8ファイルを検索
@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: が必要

NG vs OK:スペースを含むキーワードの指定
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 内のパイプは ^ でエスケープ

NG vs OK: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 はディレクトリを指定するときにパスが必要

NG vs OK:/sのパス指定
rem NG: ディレクトリ名だけ(ファイルパターンが必要)
findstr /s "ERROR" C:\logs\

rem OK: ワイルドカード付きで指定
findstr /s "ERROR" C:\logs\*.log
findstr /s "ERROR" C:\logs\*.*

関連記事

よくある質問

Q. findstrで「行を含まないファイル」を検索するにはどうすればよいですか?
A. まずfindstr /s /m "キーワード" *.logでキーワードを含むファイル名を取得し、全ファイルのリストとの差分を取る方法があります。またはfindstr /v /m "キーワード"は使えません(/vと/mの組み合わせは期待通りに動作しない場合があります)。この用途はPowerShellのGet-ChildItem | Where-Object { -not (Select-String ...) }の方が確実です。
Q. findstrで前後の行(コンテキスト)も表示したいです。
A. findstrにはコンテキスト表示機能がありません。マッチした行の前後N行を表示したい場合はPowerShellのSelect-String -Context 前,後を使います。例: Get-ChildItem *.log | Select-String "ERROR" -Context 2,2でマッチ行の前2行・後2行を表示できます。
Q. 検索結果が文字化けします。どう対処しますか?
A. ログファイルの文字コードがUTF-8(特にBOMなし)の場合、findstrがSJISとして読み込むため文字化けします。対処法は①ログファイルをSJISに変換する、②PowerShellのSelect-String -Encoding UTF8を使う、③英数字のみのキーワードで検索する(ASCII文字はSJIS/UTF-8共通のため影響を受けない)の3つです。
Q. findstrで大量のファイルを検索すると遅いです。改善方法はありますか?
A. いくつかの方法があります。①/mオプションでファイル名だけ取得(行内容の出力をしないので高速)、②検索対象のファイルパターンを絞り込む(全拡張子*.*より*.logの方が速い)、③期間で絞ったファイルのリストを事前に作成して/f:で渡す、④PowerShellのSelect-Stringはパイプラインで並列処理される場合があり大量ファイルで有利なこともあります。
Q. findstrの正規表現で「1回以上の繰り返し」(+)を使いたいです。
A. findstrの正規表現に+はありません。代替として.*を組み合わせて近似表現を作ります(例: ERR.*でERRに何かが続くパターン)。ただし完全な+の動作にはなりません。本格的な正規表現が必要な場合はPowerShellのSelect-Stringを使ってください。PowerShellは.NETの正規表現エンジンを使うため、+?|()\d\wなど標準的な記法がすべて使えます。