バッチファイルでファイル一覧を取得するのは、ログ集計・バックアップ確認・定期レポート作成など自動化の定番パターンです。
この記事では バッチファイルで指定フォルダ配下のファイル一覧を取得する全手法 を体系的に解説します。基本の1行コマンドから「拡張子フィルタ」「再帰的全取得」「サイズ・日時付きCSV出力」「forfiles 日付フィルタ」まで網羅します。
- dir /b でファイル一覧を取得する方法(基本)
- 拡張子・ファイル名パターンでフィルタする方法
- サブフォルダも含めて再帰的にすべて取得する方法(dir /s)
- for ループでファイル一覧を1件ずつ処理する方法
- ファイルサイズ・更新日時付きのCSVに出力する方法
- ファイル数をカウントする方法
- 日付・日数でフィルタする方法(forfiles)
- 落とし穴5選・実践例3本・FAQ6問
1. 基本:dir /b でファイル一覧を取得
dir コマンドに /b(シンプル表示)を付けると、ファイル名だけのシンプルなリストが得られます。
1-1. 最もシンプルな1行
:: /b : ファイル名のみ(ヘッダー・フッターなし) :: /a-d : ディレクトリを除外してファイルのみ表示(重要) dir /b /a:-d "C:\work" :: 出力例: :: report.txt :: data.csv :: script.bat
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 /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
/a:-d オプションを追加してください。dir /b /a:-d "C:\work" とすることでファイルのみが表示されます。/a:-d は「ディレクトリ(d)属性を持たない(-)もの」を意味します。dir /b /s /a:-d "C:\work" の /s オプションでサブフォルダを再帰的に検索します。または for /r "C:\work" %%F in (*) do echo %%F でループ処理も可能です。dir /b /a:-d "C:\work\*.txt" のようにワイルドカードで指定します。複数拡張子を一度に取得したい場合は for /f ... in ('dir /b /a:-d ... ^| findstr /i "\.(txt^|csv)$"') のように findstr の正規表現を使います。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 してカウントする方法も使えます。for /r %%F in (*) do echo %%~tF %%~zF %%~nxF で更新日時(%%~tF)とサイズ(%%~zF)を取得できます。または forfiles /c "cmd /c echo @FDATE @FSIZE @FILE" も使えます。dir /b /a:-d /a:h "C:\work"(隠しファイルのみ)または dir /b /a:h-d "C:\work" を使います。通常ファイルと隠しファイル両方を含める場合は PowerShell の Get-ChildItem -Force -File "C:\work" が最も確実です。