【bat】バッチファイルで指定フォルダ配下のファイル一覧を取得する方法完全ガイド|dir・for・拡張子フィルタ・CSV出力・再帰・実践パターンまで

バッチファイルでファイル一覧を取得するのは、ログ集計・バックアップ確認・定期レポート作成など自動化の定番パターンです。

この記事では バッチファイルで指定フォルダ配下のファイル一覧を取得する全手法 を体系的に解説します。基本の1行コマンドから「拡張子フィルタ」「再帰的全取得」「サイズ・日時付きCSV出力」「forfiles 日付フィルタ」まで網羅します。

この記事でわかること

  • dir /b でファイル一覧を取得する方法(基本)
  • 拡張子・ファイル名パターンでフィルタする方法
  • サブフォルダも含めて再帰的にすべて取得する方法(dir /s)
  • for ループでファイル一覧を1件ずつ処理する方法
  • ファイルサイズ・更新日時付きのCSVに出力する方法
  • ファイル数をカウントする方法
  • 日付・日数でフィルタする方法(forfiles)
  • 落とし穴5選・実践例3本・FAQ6問
スポンサーリンク
  1. 1. 基本:dir /b でファイル一覧を取得
    1. 1-1. 最もシンプルな1行
    2. 1-2. 存在チェック付き(エラーハンドリング)
  2. 2. dir コマンドの主要オプション
  3. 3. 拡張子・ファイル名パターンでフィルタ
    1. 3-1. 拡張子でフィルタ(ワイルドカード)
    2. 3-2. findstr で柔軟なフィルタ
  4. 4. サブフォルダも含めて再帰的に取得
    1. 4-1. dir /s でフルパスリスト
    2. 4-2. for /r でループ処理
  5. 5. ファイル一覧をCSV・テキストファイルに出力
    1. 5-1. テキストファイルに出力(シンプル)
    2. 5-2. ファイルサイズ・更新日時付きCSV出力
    3. 5-3. for /r を使ったサブフォルダ含む詳細CSV
  6. 6. ファイル数をカウント
    1. 6-1. find /c でカウント(最短1行)
    2. 6-2. for /r でカウント(変数に格納)
  7. 7. forfiles で日付・サイズ条件でフィルタ
    1. 7-1. 指定日数以上前に更新されたファイルを取得
    2. 7-2. forfiles の主要変数
  8. 8. for 変数修飾子(ファイル情報取得)
  9. 9. 落とし穴5選と対策
    1. 落とし穴1:dir /b だけだとフォルダ名も混入する
    2. 落とし穴2:パスにスペースが含まれると for ループが分割される
    3. 落とし穴3:for /f で dir の出力をパイプするとき ^ でエスケープが必要
    4. 落とし穴4:for /r は空フォルダでも一致パターンを探しに行くので遅くなる
    5. 落とし穴5:対象フォルダにファイルがないと dir がエラーを返す
  10. 10. 実践例3本
    1. 実践例1:複数フォルダのファイル一覧を1つのCSVに統合
    2. 実践例2:新しいファイルのみ差分コピー(バックアップ)
    3. 実践例3:古いファイルを検出してCSVに記録してからアーカイブ移動
  11. まとめ:使い分け早見表
  12. FAQ

1. 基本:dir /b でファイル一覧を取得

dir コマンドに /b(シンプル表示)を付けると、ファイル名だけのシンプルなリストが得られます。

1-1. 最もシンプルな1行

:: /b : ファイル名のみ(ヘッダー・フッターなし)
:: /a-d : ディレクトリを除外してファイルのみ表示(重要)
dir /b /a:-d "C:\work"

:: 出力例:
:: report.txt
:: data.csv
:: script.bat
/a:-d を付けないとフォルダ名も混入する
dir /b だけだとファイルもフォルダも両方表示されます。ファイルのみに絞るには /a:-d(ディレクトリ属性を除外)または /a-d を必ず付けてください。フォルダ一覧が必要な場合は バッチファイルでフォルダ一覧を取得する方法完全ガイド を参照してください。

1-2. 存在チェック付き(エラーハンドリング)

@echo off
setlocal enabledelayedexpansion

set "TARGET=C:\work"

if not exist "%TARGET%\" (
    echo [ERROR] フォルダが見つかりません: %TARGET%
    exit /b 1
)

set "COUNT=0"
for /f "delims=" %%F in ('dir /b /a:-d "%TARGET%" 2^>nul') do (
    echo %%F
    set /a COUNT+=1
)

if !COUNT! equ 0 (
    echo ファイルが見つかりませんでした
) else (
    echo 合計: !COUNT! ファイル
)
endlocal

2. dir コマンドの主要オプション

オプション 意味 使用例
/b ファイル名のみ表示(ヘッダー・フッターなし) dir /b "C:\work"
/s サブフォルダも再帰的に検索 dir /b /s "C:\work"
/a:-d ディレクトリを除外(ファイルのみ) dir /b /a:-d "C:\work"
/a:d ディレクトリのみ表示 dir /b /a:d "C:\work"
/a:h 隠しファイルを含める dir /b /a:h "C:\work"
/o:n 名前順でソート dir /b /o:n "C:\work"
/o:-d 更新日時の新しい順 dir /b /o:-d "C:\work"
/o:s ファイルサイズ順(小さい順) dir /b /o:s "C:\work"
/o:-s ファイルサイズ順(大きい順) dir /b /o:-s "C:\work"

3. 拡張子・ファイル名パターンでフィルタ

特定の拡張子や名前パターンのファイルだけを取得するパターンです。

3-1. 拡張子でフィルタ(ワイルドカード)

:: .txt ファイルのみ
dir /b /a:-d "C:\work\*.txt"

:: .csv ファイルのみ(再帰あり)
dir /b /s /a:-d "C:\work\*.csv"

:: "log" を含むファイル
dir /b /a:-d "C:\work\*log*"

:: "report_" で始まるファイル
dir /b /a:-d "C:\work\report_*"

3-2. findstr で柔軟なフィルタ

@echo off

:: "2024" を含むファイルのみ(大文字小文字区別なし)
for /f "delims=" %%F in ('dir /b /a:-d "C:\work" ^| findstr /i "2024"') do (
    echo %%F
)

:: .txt または .csv のみ(正規表現)
for /f "delims=" %%F in ('dir /b /a:-d "C:\work" ^| findstr /i "\.(txt^|csv)$"') do (
    echo %%F
)

:: 特定パターンを除外("temp" を含まないファイル)
for /f "delims=" %%F in ('dir /b /a:-d "C:\work" ^| findstr /v /i "temp"') do (
    echo %%F
)

4. サブフォルダも含めて再帰的に取得

/s オプションで、指定フォルダの下にある全サブフォルダのファイルも一括で取得できます。

4-1. dir /s でフルパスリスト

:: /s: サブフォルダを再帰的に検索(フルパスで出力される)
dir /b /s /a:-d "C:\work"

:: 特定拡張子のみ再帰的に取得
dir /b /s /a:-d "C:\work\*.log"

:: エラー(サブフォルダが空の場合など)を非表示にする
dir /b /s /a:-d "C:\work" 2>nul

4-2. for /r でループ処理

@echo off
setlocal enabledelayedexpansion

set "TARGET=C:\work"
set "COUNT=0"

:: for /r: 指定フォルダ以下を再帰的にループ
for /r "%TARGET%" %%F in (*) do (
    :: %%~nxF: ファイル名のみ, %%F: フルパス
    echo %%F
    set /a COUNT+=1
)
echo 合計: !COUNT! ファイル
endlocal
dir /s と for /r の違い
dir /b /s は一覧表示・ファイル出力向きでシンプルです。for /r %%F in (*) は各ファイルに対してコマンドを実行(コピー・削除・処理)する用途に向いています。複数フォルダをループ処理する詳細は 複数フォルダをループして一括処理する方法完全ガイド を参照してください。

5. ファイル一覧をCSV・テキストファイルに出力

ファイル一覧を記録・共有・比較するためにファイルに出力するパターンです。

5-1. テキストファイルに出力(シンプル)

:: ファイル名のみ保存
dir /b /a:-d "C:\work" > "C:\output\filelist.txt"

:: フルパスで保存(/s オプション)
dir /b /s /a:-d "C:\work" > "C:\output\filelist_full.txt"

:: 日付付きファイル名で保存
@echo off
for /f "tokens=2 delims==." %%D in ('wmic os get LocalDateTime /value ^| findstr LocalDateTime') do set "DT=%%D"
dir /b /a:-d "C:\work" > "C:\output\filelist_%DT:~0,8%.txt"
echo 出力完了

5-2. ファイルサイズ・更新日時付きCSV出力

@echo off
setlocal enabledelayedexpansion

set "TARGET=C:\work"
set "OUT=C:\output\filelist.csv"
set "NUM=0"

:: ヘッダー行
echo No,ファイル名,サイズ(Byte),更新日時,フルパス > "%OUT%"

for /f "delims=" %%F in ('dir /b /a:-d "%TARGET%" 2^>nul') do (
    set /a NUM+=1
    set "FPATH=%TARGET%\%%F"
    :: %%~zF: サイズ(Byte), %%~tF: 更新日時
    for %%G in ("!FPATH!") do (
        echo !NUM!,%%~nxG,%%~zG,%%~tG,%%~fG >> "%OUT%"
    )
)

echo [OK] CSV出力完了: !NUM! 件 -> %OUT%
endlocal

5-3. for /r を使ったサブフォルダ含む詳細CSV

@echo off
setlocal enabledelayedexpansion

set "TARGET=C:\work"
set "OUT=C:\output\filelist_all.csv"
set "NUM=0"

echo No,ファイル名,拡張子,サイズ(Byte),更新日時,フルパス > "%OUT%"

for /r "%TARGET%" %%F in (*) do (
    set /a NUM+=1
    echo !NUM!,%%~nF,%%~xF,%%~zF,%%~tF,%%~fF >> "%OUT%"
)

echo [OK] CSV出力完了: !NUM! 件 -> %OUT%
endlocal

日付をファイル名に使う方法の詳細は 日付と時間をファイル名に挿入する方法完全ガイド を参照してください。

6. ファイル数をカウント

処理前の確認や定期監視に使える、ファイル数カウントのパターンです。

6-1. find /c でカウント(最短1行)

:: カレントフォルダのファイル数(フォルダ除く)
dir /b /a:-d "C:\work" 2>nul | find /c /v ""

:: サブフォルダ含む全ファイル数
dir /b /s /a:-d "C:\work" 2>nul | find /c /v ""

:: 特定拡張子のファイル数
dir /b /a:-d "C:\work\*.txt" 2>nul | find /c /v ""

6-2. for /r でカウント(変数に格納)

@echo off
setlocal enabledelayedexpansion

set "TARGET=C:\work"
set "MAX=500"
set "COUNT=0"

for /r "%TARGET%" %%F in (*) do set /a COUNT+=1

echo ファイル数: !COUNT!

if !COUNT! gtr %MAX% (
    echo [WARN] ファイルが %MAX% 件を超えています!
)
endlocal

7. forfiles で日付・サイズ条件でフィルタ

forfiles コマンドは更新日付・ファイルサイズでのフィルタが得意で、定期クリーンアップや監査ログの生成に使えます。

7-1. 指定日数以上前に更新されたファイルを取得

@echo off

:: /p: 対象フォルダ
:: /d: 日付フィルタ(-30 = 30日以上前に更新)
:: /m: ファイルマスク(拡張子フィルタ)
:: @FILE: ファイル名, @FDATE: 更新日付, @FSIZE: サイズ(Byte)
forfiles /p "C:\work" /d -30 /c "cmd /c echo @FILE @FDATE @FSIZE"

:: 30日以上前の .log ファイルのみ
forfiles /p "C:\work" /m "*.log" /d -30 /c "cmd /c echo @FILE"

:: 今日更新されたファイル
forfiles /p "C:\work" /d +0 /c "cmd /c echo @FILE @FTIME"

7-2. forfiles の主要変数

変数 意味
@FILE ファイル名(引用符付き) “report.txt”
@PATH フルパス(引用符付き) “C:\work\report.txt”
@RELPATH 相対パス(引用符付き) “.\sub\report.txt”
@FSIZE ファイルサイズ(バイト) 1024
@FDATE 更新日付 2024/01/15
@FTIME 更新時刻 14:30:00
@ISDIR フォルダなら TRUE TRUE / FALSE
@EXT 拡張子(ドットなし) txt

日付フィルタを使ったファイル削除の詳細は 指定期間以前のファイルを自動削除する方法完全ガイド を参照してください。

8. for 変数修飾子(ファイル情報取得)

for %%F in (...) で取得したファイルパスから、各種情報を修飾子で取り出せます。

修飾子 意味 例(%%F = “C:\work\report.txt”)
%%F 元の値(フルパスまたは相対) C:\work\report.txt
%%~nF 拡張子なしのファイル名 report
%%~xF 拡張子のみ(ドット含む) .txt
%%~nxF ファイル名 + 拡張子 report.txt
%%~dpF ドライブ + フォルダパス C:\work\
%%~fF 完全修飾パス(フルパス) C:\work\report.txt
%%~zF ファイルサイズ(バイト) 2048
%%~tF 更新日時 2024/01/15 14:30
%%~aF ファイル属性 –a——

9. 落とし穴5選と対策

落とし穴1:dir /b だけだとフォルダ名も混入する

:: NG: /b だけではフォルダ名も一覧に含まれる
dir /b "C:\work"
:: → backup/ temp/ report.txt data.csv が全部出てくる

:: OK: /a:-d でディレクトリ属性を除外してファイルのみにする
dir /b /a:-d "C:\work"
:: → report.txt data.csv のみ

落とし穴2:パスにスペースが含まれると for ループが分割される

:: NG: パスのスペースで分割されて処理が崩れる
for /f "delims=" %%F in ('dir /b /a:-d C:\My Documents') do echo %%F

:: OK: パスを必ずダブルクォートで囲む
for /f "delims=" %%F in ('dir /b /a:-d "C:\My Documents"') do echo %%F

:: OK: 変数展開もクォートで囲む
set "TARGET=C:\My Documents"
for /f "delims=" %%F in ('dir /b /a:-d "%TARGET%"') do echo %%F

落とし穴3:for /f で dir の出力をパイプするとき ^ でエスケープが必要

:: NG: | や > をエスケープしないとエラーになる
for /f "delims=" %%F in ('dir /b /a:-d "C:\work" | findstr "log"') do echo %%F

:: OK: バッチファイル内では ^ でエスケープ
for /f "delims=" %%F in ('dir /b /a:-d "C:\work" ^| findstr "log"') do echo %%F

:: OK: リダイレクトも同様
for /f "delims=" %%F in ('dir /b /s /a:-d "C:\work" 2^>nul') do echo %%F

落とし穴4:for /r は空フォルダでも一致パターンを探しに行くので遅くなる

:: 注意: for /r は指定フォルダ以下の全フォルダを走査するため
:: サブフォルダが多いと遅い場合がある
for /r "C:\work" %%F in (*.txt) do echo %%F

:: 高速化: dir /s /b で先にリストを取得してから処理
for /f "delims=" %%F in ('dir /b /s /a:-d "C:\work\*.txt" 2^>nul') do (
    echo %%F
)

落とし穴5:対象フォルダにファイルがないと dir がエラーを返す

:: NG: ファイルなし時に "ファイルが見つかりません" エラーが出る
for /f "delims=" %%F in ('dir /b /a:-d "C:\empty_folder"') do echo %%F

:: OK: 2>nul でエラーを抑制
for /f "delims=" %%F in ('dir /b /a:-d "C:\work" 2^>nul') do echo %%F

:: OK: 事前に if exist でチェック
if exist "C:\work\*" (
    for /f "delims=" %%F in ('dir /b /a:-d "C:\work"') do echo %%F
) else (
    echo ファイルがありません
)

エラーハンドリングの詳細は ERRORLEVELを使ったエラーハンドリング完全ガイド を参照してください。

10. 実践例3本

実践例1:複数フォルダのファイル一覧を1つのCSVに統合

複数の対象フォルダを順番に処理し、全ファイル情報を1つのCSVに集約するパターンです。

@echo off
setlocal enabledelayedexpansion

set "OUT=C:\reports\all_files.csv"
set "NUM=0"

echo No,フォルダ,ファイル名,拡張子,サイズ(Byte),更新日時 > "%OUT%"

:: 対象フォルダを列挙
for %%T in ("C:\projects" "C:\logs" "C:\data") do (
    if exist "%%~T\" (
        for /r "%%~T" %%F in (*) do (
            set /a NUM+=1
            echo !NUM!,%%~dpF,%%~nxF,%%~xF,%%~zF,%%~tF >> "%OUT%"
        )
    )
)

echo [OK] CSV出力完了: !NUM! 件 -> %OUT%
endlocal

実践例2:新しいファイルのみ差分コピー(バックアップ)

コピー先にないファイル、またはコピー先より新しいファイルだけを選んでコピーするパターンです。

@echo off
setlocal enabledelayedexpansion

set "SRC=C:\work"
set "DST=D:\backup\work"
set "COUNT=0"

if not exist "%DST%" mkdir "%DST%"

for /f "delims=" %%F in ('dir /b /a:-d "%SRC%" 2^>nul') do (
    set "SRC_FILE=%SRC%\%%F"
    set "DST_FILE=%DST%\%%F"

    :: コピー先にない場合はコピー
    if not exist "!DST_FILE!" (
        copy "!SRC_FILE!" "!DST_FILE!" >nul
        echo [COPY] %%F
        set /a COUNT+=1
    ) else (
        :: コピー先より新しい場合はコピー(robocopy /MAXAGE:0 の代替)
        xcopy "!SRC_FILE!" "!DST_FILE!" /d /y >nul 2>nul
        if !ERRORLEVEL! equ 0 (
            echo [UPDATE] %%F
            set /a COUNT+=1
        )
    )
)

echo ===== 完了: !COUNT! 件 =====
endlocal

ファイルコピーの詳細は バッチファイルでファイルをコピーする方法完全ガイド を参照してください。

実践例3:古いファイルを検出してCSVに記録してからアーカイブ移動

指定日数以上更新のないファイルを検出し、記録してからアーカイブフォルダへ移動するパターンです。

@echo off
setlocal enabledelayedexpansion

set "TARGET=C:\logs"
set "ARCHIVE=C:\logs_archive"
set "DAYS=90"
set "LOG_CSV=C:\reports\archived_%date:~0,4%%date:~5,2%%date:~8,2%.csv"
set "COUNT=0"

if not exist "%ARCHIVE%" mkdir "%ARCHIVE%"

echo ファイル名,サイズ,更新日付,移動先 > "%LOG_CSV%"

:: @PATH でフルパスのみ出力(1行1ファイル・ファイル名スペース対応)
set "TMPFILE=%TEMP%\old_files_%RANDOM%.tmp"
forfiles /p "%TARGET%" /d -%DAYS% /c "cmd /c echo @PATH" > "%TMPFILE%" 2>nul

:: usebackq delims= で1行ずつ読み込む(%%P は "C:\logs\file.txt" の形式)
for /f "usebackq delims=" %%P in ("%TMPFILE%") do (
    :: %%~P でクォートを除去したフルパス、%%~nxP でファイル名
    if exist %%P (
        set "FNAME=%%~nxP"
        set "FSIZE=%%~zP"
        move %%P "%ARCHIVE%\" >nul
        if !ERRORLEVEL! equ 0 (
            echo !FNAME!,!FSIZE!,%ARCHIVE% >> "%LOG_CSV%"
            set /a COUNT+=1
        )
    )
)

del "%TMPFILE%" 2>nul
echo ===== アーカイブ完了: !COUNT! 件 -> %ARCHIVE% =====
echo ログ: %LOG_CSV%
endlocal

ファイル移動の詳細は ファイルを別フォルダに移動する方法完全ガイド を参照してください。

まとめ:使い分け早見表

やりたいこと コマンド ポイント
ファイル名だけ一覧表示 dir /b /a:-d "パス" /a:-d でフォルダを除外
拡張子でフィルタ dir /b /a:-d "パス\*.txt" ワイルドカード使用可
再帰的に全ファイル取得 dir /b /s /a:-d "パス" フルパスで出力
ループで1件ずつ処理 for /r "パス" %%F in (*) do コピー・削除・処理向き
CSV出力(詳細情報付き) for /r + %%~zF %%~tF でCSV サイズ・日時も取得可能
ファイル数カウント dir /b /a:-d 2>nul | find /c /v "" 1行で取得可能
日付・日数でフィルタ forfiles /d -日数 /m *.拡張子 定期クリーンアップ向き
名前パターンで絞り込み dir /b /a:-d 2>nul ^| findstr "pattern" 正規表現も使用可

setlocal enabledelayedexpansion 完全ガイド も合わせて参照してください。

FAQ

Q. dir /b でファイル一覧を取得するとフォルダ名も混じってしまいます。
A. /a:-d オプションを追加してください。dir /b /a:-d "C:\work" とすることでファイルのみが表示されます。/a:-d は「ディレクトリ(d)属性を持たない(-)もの」を意味します。
Q. サブフォルダの中のファイルも全部まとめて取得したい。
A. dir /b /s /a:-d "C:\work"/s オプションでサブフォルダを再帰的に検索します。または for /r "C:\work" %%F in (*) do echo %%F でループ処理も可能です。
Q. 特定の拡張子のファイルだけを取得したい。
A. dir /b /a:-d "C:\work\*.txt" のようにワイルドカードで指定します。複数拡張子を一度に取得したい場合は for /f ... in ('dir /b /a:-d ... ^| findstr /i "\.(txt^|csv)$"') のように findstr の正規表現を使います。
Q. ファイル数だけを取得して変数に入れたい。
A. for /f %%N in ('dir /b /a:-d "C:\work" 2^>nul ^| find /c /v ""') do set "COUNT=%%N" で変数に格納できます。または for /r ループ内で set /a COUNT+=1 してカウントする方法も使えます。
Q. ファイルの更新日時やサイズも一緒に取得したい。
A. for /r %%F in (*) do echo %%~tF %%~zF %%~nxF で更新日時(%%~tF)とサイズ(%%~zF)を取得できます。または forfiles /c "cmd /c echo @FDATE @FSIZE @FILE" も使えます。
Q. 隠しファイルも含めて一覧取得したい。
A. dir /b /a:-d /a:h "C:\work"(隠しファイルのみ)または dir /b /a:h-d "C:\work" を使います。通常ファイルと隠しファイル両方を含める場合は PowerShell の Get-ChildItem -Force -File "C:\work" が最も確実です。