【bat】バッチファイルでファイルサイズを取得する完全ガイド|%%~zF・単位変換・合計・条件分岐・実践パターンまで徹底解説

【bat】バッチファイルで指定したファイルのサイズを取得する方法 bat

バッチファイルでファイルサイズを取得したい場面は多くあります。「ログが一定サイズを超えたらローテーション」「空ファイルを自動削除」「大容量ファイルを別フォルダに移動」などの自動化でサイズ取得は必須スキルです。Windowsバッチには %%~zF という強力な修飾子があり、外部ツールなしで即座にバイト数が取得できます。本記事ではその基本から単位変換・合計計算・条件分岐・実践応用まで完全に解説します。

この記事でわかること

  • %%~zF 修飾子でファイルサイズをバイト単位で取得する方法
  • バイト → KB / MB / GB への単位変換(set /a と PowerShell)
  • forfiles コマンドでサイズを取得する方法
  • フォルダ内の全ファイルサイズを合計する方法
  • サイズで条件分岐・空ファイル検出・大容量ファイルの検出
  • ログ監視・サイズ順CSV・自動アーカイブの実践例3本
スポンサーリンク

1. 基本:%%~zF 修飾子でファイルサイズを取得する

Windowsバッチでファイルサイズを取得する最もシンプルな方法が for ループの %%~zF 修飾子です。%%F はループ変数(任意の1文字)、~z がサイズを返す修飾子です。バイト単位の整数が返るため、そのまま set /a での計算にも使えます。

@echo off
setlocal

:: 1ファイルのサイズを取得して変数に格納
set FILE=C:\work\data.csv

for %%F in ("%FILE%") do set SIZE=%%~zF

echo ファイル : %FILE%
echo サイズ   : %SIZE% bytes
ファイルが存在しない場合 SIZE が未定義になる
ファイルが存在しなければ for ループは実行されず、SIZE 変数が設定されません。必ず事前に if exist でファイルの存在を確認してください。
@echo off
setlocal

set FILE=C:\work\data.csv

:: 存在確認してからサイズ取得
if not exist "%FILE%" (
    echo [ERROR] ファイルが見つかりません: %FILE%
    exit /b 1
)

for %%F in ("%FILE%") do set SIZE=%%~zF
echo サイズ: %SIZE% bytes

%%~z 以外にも、サイズ取得と組み合わせて使えるファイル情報修飾子があります。ファイル名・パス・更新日時・属性などの修飾子については バッチファイルのパス・ファイル名取得完全ガイド も参照してください。

2. バイト → KB / MB / GB に単位変換する

%%~zF はバイト単位の整数値を返します。ログ出力や判定に使いやすい単位に変換する方法を示します。

2-1. set /a による整数変換(高速・軽量)

@echo off
setlocal

set FILE=C:\work\data.csv
for %%F in ("%FILE%") do set SIZE_B=%%~zF

:: KB(1024で割る)
set /a SIZE_KB=%SIZE_B% / 1024

:: MB(1024*1024で割る)
set /a SIZE_MB=%SIZE_B% / 1048576

:: GB(1024*1024*1024で割る)
set /a SIZE_GB=%SIZE_B% / 1073741824

echo バイト : %SIZE_B% B
echo キロ   : %SIZE_KB% KB
echo メガ   : %SIZE_MB% MB
echo ギガ   : %SIZE_GB% GB
set /a は 32bit 整数(最大約 2.1GB)までしか扱えない
set /a は32bitの符号付き整数計算のため、約2,147,483,647バイト(約2.1GB)を超えるファイルでは計算が正しくなりません。2GBを超えるファイルを扱う場合はPowerShellを使ってください(後述)。

2-2. 適切な単位を自動判定して表示する

@echo off
setlocal enabledelayedexpansion

set FILE=C:\work\data.csv
for %%F in ("%FILE%") do set SIZE_B=%%~zF

:: 単位を自動判定して表示
set /a SIZE_KB=%SIZE_B% / 1024
set /a SIZE_MB=%SIZE_B% / 1048576

if %SIZE_MB% geq 1 (
    echo サイズ: %SIZE_MB% MB  ^(%SIZE_B% bytes^)
) else if %SIZE_KB% geq 1 (
    echo サイズ: %SIZE_KB% KB  ^(%SIZE_B% bytes^)
) else (
    echo サイズ: %SIZE_B% bytes
)

2-3. PowerShell で精確な単位変換(小数点・2GB超対応)

@echo off

:: PowerShellで小数点付きMB表示(例: 1.23 MB)
set FILE=C:\work\bigfile.zip

for /f "usebackq delims=" %%S in (`powershell -NoProfile -Command "[Math]::Round((Get-Item '%FILE%').Length / 1MB, 2).ToString() + ' MB'"`) do (
    echo サイズ: %%S
)

:: 2GBを超えるファイルでも正確に取得
for /f "usebackq delims=" %%S in (`powershell -NoProfile -Command "(Get-Item '%FILE%').Length"`) do (
    echo バイト数: %%S
)

3. forfiles コマンドでファイルサイズを取得する

forfiles はフォルダ内のファイルをまとめて処理するコマンドです。@fsize 変数でファイルサイズをバイト単位で参照できます。拡張子フィルタや日付フィルタと組み合わせると強力です。

forfiles 変数 内容
@fname ファイル名(ダブルクォート付き)
@fsize ファイルサイズ(バイト)
@fdate 更新日付
@ftime 更新時刻
@path フルパス(ダブルクォート付き)
@isdir ディレクトリなら 1、ファイルなら 0
:: 指定フォルダ内の全ファイルのサイズを表示
forfiles /P "C:\work" /C "cmd /c echo @fname @fsize bytes"

:: 拡張子でフィルタ(.log ファイルのみ)
forfiles /P "C:\logs" /M "*.log" /C "cmd /c echo @fname @fsize bytes"

:: サブフォルダも再帰的に処理(/S オプション)
forfiles /P "C:\work" /S /C "cmd /c echo @path @fsize bytes"

:: 1MB(1048576バイト)以上のファイルのみ表示
forfiles /P "C:\work" /C "cmd /c if @fsize gtr 1048576 echo @fname @fsize bytes"
forfiles のサイズ比較は gtr/lss で行う
forfiles/C オプション内では通常の if 文が使えますが、@fsize はシェル変数のため gtrlssequ で比較します。なお forfiles はサブフォルダなしでエラーが出るときは /D オプションを省略してください。

4. フォルダ内の全ファイルサイズを合計する

4-1. for ループで合計(2GB未満のフォルダ向け)

@echo off
setlocal enabledelayedexpansion

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

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

set /a TOTAL_MB=%TOTAL% / 1048576

echo ファイル数   : %COUNT% 件
echo 合計サイズ   : %TOTAL% bytes
echo             ( %TOTAL_MB% MB )

4-2. dir コマンドで合計サイズを一発取得

:: dir /s の最終行に合計サイズが表示される
:: "X 個のファイル           X,XXX,XXX バイト" の行を抽出
@echo off

set TARGET=C:\work

:: dir の出力から合計行のみ抽出(日本語環境)
for /f "tokens=1-4" %%A in ('dir /s /a-d "%TARGET%" ^| findstr /C:"バイト" ^| findstr /V "空き"') do (
    echo 合計: %%A %%B %%C %%D
)

:: 英語環境向け(bytes の行を抽出)
:: for /f "tokens=3" %%A in ('dir /s /a-d "%TARGET%" ^| findstr "bytes"') do echo 合計: %%A

4-3. PowerShell で精確な合計(2GB超対応・サブフォルダ含む)

2GBを超えるフォルダの合計サイズは set /a の32bit制限により正しく計算できません。PowerShell の Measure-Object を使うと64bit整数で正確に取得できます。

5. ファイルサイズを使った条件分岐・検出パターン

5-1. 空ファイル(0バイト)を検出する

@echo off
setlocal

set FILE=C:\work\output.csv

if not exist "%FILE%" (
    echo [ERROR] ファイルが存在しません
    exit /b 1
)

for %%F in ("%FILE%") do set SIZE=%%~zF

if %SIZE% equ 0 (
    echo [WARN] 空ファイルです: %FILE%
    exit /b 1
) else (
    echo [OK] ファイルサイズ: %SIZE% bytes
)

5-2. サイズが一定以上のファイルを検出する

@echo off
setlocal enabledelayedexpansion

:: 10MB(10,485,760 bytes)を超えるファイルを一覧表示
set LIMIT=10485760
set TARGET=C:\work

echo === 10MB超のファイル ===
for /r "%TARGET%" %%F in (*) do (
    if %%~zF gtr %LIMIT% (
        set /a SIZE_MB=%%~zF / 1048576
        echo [!SIZE_MB! MB] %%~fF
    )
)

5-3. ログファイルが指定サイズを超えたか判定する(ローテーション判定)

@echo off
setlocal

set LOGFILE=C:\logs\app.log

:: ログが 5MB を超えたらローテーション
set ROTATE_LIMIT=5242880

if not exist "%LOGFILE%" exit /b 0

for %%F in ("%LOGFILE%") do set LOG_SIZE=%%~zF

if %LOG_SIZE% gtr %ROTATE_LIMIT% (
    echo ログサイズ %LOG_SIZE% bytes がしきい値を超えました。ローテーションします。
    call :rotate_log
) else (
    echo ログサイズ %LOG_SIZE% bytes は正常範囲内です。
)
exit /b 0

:rotate_log
    :: 日付を使ったアーカイブ名で退避
    for /f %%D in ('powershell -Command "Get-Date -Format yyyyMMdd_HHmmss"') do set DT=%%D
    ren "%LOGFILE%" "app_%DT%.log"
    echo ログをアーカイブしました: app_%DT%.log
    exit /b 0

ファイルサイズによる条件分岐のさらに詳しいパターンについては バッチファイルでファイルサイズを取得して条件分岐する方法 も参照してください。

6. 複数ファイルのサイズ一覧取得とソート

6-1. フォルダ内ファイルのサイズ一覧をCSVに出力する

@echo off
setlocal enabledelayedexpansion

set TARGET=C:\work
set OUTPUT=%~dpn0_filelist.csv

echo ファイル名,サイズ(bytes),サイズ(KB),更新日時 > "%OUTPUT%"

for /r "%TARGET%" %%F in (*) do (
    set /a SIZE_KB=%%~zF / 1024
    echo %%~nxF,%%~zF,!SIZE_KB!,%%~tF >> "%OUTPUT%"
)

echo CSVを出力しました: %OUTPUT%

6-2. ファイルをサイズ順(降順)に表示する

@echo off

:: PowerShell でサイズ降順に一覧表示
set TARGET=C:\work

powershell -NoProfile -Command "Get-ChildItem -Path '%TARGET%' -Recurse -File | Sort-Object Length -Descending | Select-Object -First 20 | Format-Table Name, @{Name='Size(KB)'; Expression={[Math]::Round($_.Length/1KB,1)}}, LastWriteTime -AutoSize"

:: サイズ順の詳細は関連記事も参照

サイズ順の一覧をCSVやログとして保存する方法については バッチファイルで指定フォルダ内のファイルをサイズ順に並べてログ出力する方法 も参照してください。

フォルダ内のファイル一覧を取得するさまざまなパターンについては バッチファイルで指定フォルダ配下のファイル一覧を取得する方法完全ガイド も参照してください。

7. 実践例3本

実践例1:ログファイルが指定サイズを超えたら自動でローテーションする

アプリケーションのログが肥大化した場合に、バッチスケジューラから定期実行してログを自動圧縮・退避します。

@echo off
setlocal enabledelayedexpansion

set LOGDIR=C:\logs
set ROTATE_MB=5
set ROTATE_BYTES=5242880

echo === ログローテーションチェック ===

for %%F in ("%LOGDIR%\*.log") do (
    if %%~zF gtr %ROTATE_BYTES% (
        set /a SIZE_MB=%%~zF / 1048576
        echo [%%~nxF] !SIZE_MB! MB - しきい値超過。ローテーション実行...

        :: タイムスタンプ付きアーカイブ名で移動
        for /f %%D in ('powershell -Command "Get-Date -Format yyyyMMdd_HHmmss"') do (
            move "%%~fF" "%LOGDIR%\%%~nF_%%D.log" >nul 2>&1
            echo   → %LOGDIR%\%%~nF_%%D.log に移動しました
        )
    ) else (
        set /a SIZE_KB=%%~zF / 1024
        echo [%%~nxF] !SIZE_KB! KB - 正常範囲
    )
)

echo === チェック完了 ===

実践例2:フォルダ内のファイルサイズを集計してサマリーレポートを出力する

@echo off
setlocal enabledelayedexpansion

set TARGET=%~1
if "%TARGET%"=="" set TARGET=%~dp0

set REPORT=%~dpn0_report.txt
set TOTAL=0
set COUNT=0
set LARGE_COUNT=0
set EMPTY_COUNT=0

for /r "%TARGET%" %%F in (*) do (
    set /a TOTAL+=%%~zF
    set /a COUNT+=1
    if %%~zF equ 0 set /a EMPTY_COUNT+=1
    if %%~zF gtr 10485760 set /a LARGE_COUNT+=1
)

set /a TOTAL_MB=%TOTAL% / 1048576

for /f %%D in ('powershell -Command "Get-Date -Format 'yyyy-MM-dd HH:mm:ss'"') do set NOW=%%D

echo ======================================== > "%REPORT%"
echo フォルダサイズレポート                   >> "%REPORT%"
echo 生成日時  : %NOW%                         >> "%REPORT%"
echo 対象フォルダ: %TARGET%                    >> "%REPORT%"
echo ---------------------------------------- >> "%REPORT%"
echo ファイル数  : %COUNT% 件                  >> "%REPORT%"
echo 合計サイズ  : %TOTAL% bytes               >> "%REPORT%"
echo            ( %TOTAL_MB% MB )              >> "%REPORT%"
echo 空ファイル  : %EMPTY_COUNT% 件            >> "%REPORT%"
echo 10MB超      : %LARGE_COUNT% 件            >> "%REPORT%"
echo ======================================== >> "%REPORT%"

type "%REPORT%"
echo.
echo レポート: %REPORT%

実践例3:サイズが0バイトの空ファイルを一括で自動削除する

処理後に残った空のCSVや空のログファイルを自動削除します。ドライランモード付きで誤削除を防ぎます。

@echo off
setlocal enabledelayedexpansion

:: 引数で対象フォルダを指定。なければカレントフォルダ
set TARGET=%~1
if "%TARGET%"=="" set TARGET=%~dp0

:: /dry オプションで実際には削除しないドライランモード
set DRY=0
if /i "%~2"=="/dry" set DRY=1

if %DRY%==1 (
    echo [ドライランモード] 実際には削除しません
) else (
    echo [削除モード] 空ファイルを削除します
)
echo 対象: %TARGET%
echo.

set COUNT=0

for /r "%TARGET%" %%F in (*) do (
    if %%~zF equ 0 (
        set /a COUNT+=1
        if %DRY%==1 (
            echo [DRY] 削除対象: %%~fF
        ) else (
            del "%%~fF"
            if not errorlevel 1 (
                echo [削除] %%~fF
            ) else (
                echo [WARN] 削除失敗: %%~fF
            )
        )
    )
)

echo.
if %COUNT% equ 0 (
    echo 空ファイルはありませんでした
) else (
    echo %COUNT% 件の空ファイルを処理しました
)

空ファイル(0バイト)の自動削除の詳細については バッチファイルでファイルサイズが0のファイルを自動削除する方法 も参照してください。

8. まとめ:ファイルサイズ取得チートシート

やりたいこと コード例
1ファイルのサイズをバイトで取得 for %%F in ("%FILE%") do set SIZE=%%~zF
バッチ自身のサイズを取得 echo %~z0(スクリプト内で直接使用)
forループ内でサイズを取得 for /r . %%F in (*) do echo %%~zF
KB単位に変換 set /a KB=%SIZE% / 1024
MB単位に変換 set /a MB=%SIZE% / 1048576
空ファイルを検出 if %%~zF equ 0 ( ... )
一定サイズ超を検出(例: 10MB) if %%~zF gtr 10485760 ( ... )
forfiles でサイズ表示 forfiles /P . /M *.log /C "cmd /c echo @fname @fsize bytes"
2GB超ファイルのサイズをバイトで取得 powershell -Command "(Get-Item '%FILE%').Length"
フォルダ合計サイズ(PowerShell) powershell -Command "(Get-ChildItem . -Recurse -File | Measure-Object Length -Sum).Sum"

FAQ

Q%%~zF でサイズが取得できず変数が空になります。

Aファイルが存在しない場合、for ループは実行されないため変数が設定されません。まず if exist "%FILE%" でファイルの存在を確認してください。ファイルパスにスペースが含まれる場合はダブルクォートで囲む必要があります: for %%F in ("%FILE%") のように記述してください。

Q2GBを超えるファイルのサイズが正しく取得できません。

Aset /a は32bit整数(最大約2.1GB)しか扱えないため、2GBを超えると計算が壊れます。PowerShellを使ってください: for /f %%S in ('powershell -Command "(Get-Item '%FILE%').Length"') do set SIZE=%%S PowerShellは64bit整数を使用するため大容量ファイルでも正確です。

Qフォルダ全体のサイズを合計したい場合はどうすればよいですか?

Afor /r でサブフォルダを再帰的にループし、set /a TOTAL+=%%~zF で合計できます。2GBを超える場合はPowerShellの Get-ChildItem | Measure-Object Length -Sum を使ってください。また dir /s /a-d フォルダ コマンドの出力末尾にも合計サイズが表示されます。

Qforfiles でサイズが一定以上のファイルを見つけたい場合はどうしますか?

Aforfiles /P フォルダ /S /C "cmd /c if @fsize gtr 1048576 echo @fname @fsize" のように /C オプション内で if を使ってサイズ比較できます。gtr(より大きい)・lss(より小さい)・equ(等しい)で条件指定します。

Q%%~z と %%~zF の違いは何ですか?

A%%F がループ変数の名前です。変数名に任意の1文字(A〜Z)が使えます。%%~zF は「ループ変数 F のサイズ修飾子」という意味です。変数を %%A にすれば %%~zA%%I にすれば %%~zI と書きます。

Q引数で渡されたファイルのサイズを取得するにはどうしますか?

A%~z1 で第1引数のファイルサイズが直接取得できます。echo バッチに渡されたファイルのサイズ: %~z1 bytes のように使います。引数への修飾子の詳細は バッチファイルのパス・ファイル名取得完全ガイド を参照してください。