【bat】バッチファイルでファイルサイズを条件分岐に活用する完全ガイド|0バイト検出・多段階判定・変化監視・フォルダ容量・実践パターンまで

【bat】バッチファイルでファイルサイズを条件分岐に活用する完全ガイド|0バイト検出・多段階判定・変化監視・フォルダ容量・実践パターンまで bat

バッチファイルの自動化で「ファイルサイズに応じて処理を変えたい」場面は多くあります。「空ファイルを検出して削除」「ログが1MBを超えたらローテーション」「バックアップ前にディスク空き容量を確認」——これらはすべてファイルサイズの条件分岐で実現できます。この記事ではサイズ取得の基本から多段階判定・変化監視・フォルダ容量チェック・実践業務パターンまで解説します。

この記事でわかること

  • %%~zA / %%~zF 修飾子でファイルサイズをバイト単位で取得する基本
  • 0バイト(空ファイル)の検出と自動削除・スキップ処理
  • 小/中/大/特大 の多段階閾値で処理を切り替えるパターン
  • 前回サイズと比較して「ファイルが増えた/減った」を検知する方法
  • フォルダ内全ファイルの合計サイズを監視する方法
  • ログローテーション・バックアップ前容量確認の実践パターン
スポンサーリンク

ファイルサイズ条件分岐のパターン比較

パターン 判定方法 主な用途
0バイト(空)チェック if %%~zA==0 空ファイル削除・スキップ・エラー検知
単一閾値チェック if SIZE GEQ 1048576 1MB超えたらローテーション
多段階閾値チェック if/else if の連鎖 サイズ区分ごとに異なる処理
前回との差分比較 前回値をファイル保存→比較 増加検知・変化監視・アラート
フォルダ合計サイズ FOR ループで積算 フォルダ容量上限の監視

基本:%%~zA でファイルサイズを取得する

for %%A in ("ファイルパス") do set SIZE=%%~zA が基本形です。%%~zA はバイト単位の整数を返します。ファイルが存在しない場合はループが実行されず SIZE が未定義になるため、必ず if exist で存在確認してから取得します。

基本: ファイルサイズ取得と1MB閾値チェック
@echo off
setlocal

set FILEPATH=C:\work\data.csv

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

for %%A in ("%FILEPATH%") do set SIZE=%%~zA

echo ファイルサイズ: %SIZE% bytes

REM 1MB(1,048,576バイト)以上かチェック
if %SIZE% GEQ 1048576 (
    echo 1MB以上のファイルです。処理A を実行します。
) else (
    echo 1MB未満のファイルです。処理B を実行します。
)
endlocal
%%~zA と %%~zF の違い
ループ変数の文字(A や F)は任意の1文字です。変数名を %%F にした場合は %%~zF%%A にした場合は %%~zA と書きます。どちらも同じ修飾子 ~z でサイズを取得します。修飾子の詳細はファイルサイズ取得完全ガイドを参照してください。

0バイト(空ファイル)の検出と処理

空ファイルは出力処理の失敗・書き込みエラーのサインです。自動で検出してスキップ・削除・通知処理を実行しましょう。

空ファイルを検出してスキップ・削除
@echo off
setlocal

set DATAFILE=C:\work\output.csv

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

for %%A in ("%DATAFILE%") do set SIZE=%%~zA

if %SIZE% EQU 0 (
    echo [WARN] 空ファイルを検出しました: %DATAFILE%
    del "%DATAFILE%"
    echo 空ファイルを削除しました。処理をスキップします。
    exit /b 0
)

echo [OK] ファイルサイズ: %SIZE% bytes - 処理を続行します
REM ここに実際のデータ処理を記述
endlocal
フォルダ内の空ファイルを一括削除
@echo off
setlocal

set TARGETDIR=C:\work\output
set COUNT=0

for %%F in ("%TARGETDIR%\*") do (
    if %%~zF EQU 0 (
        echo 削除: %%~nxF  ^(0 bytes^)
        del "%%F"
        set /a COUNT+=1
    )
)

echo 削除した空ファイル数: %COUNT% 件
endlocal
空ファイル削除の専用ガイドもあります
空ファイルの検索・削除パターンをさらに詳しく知りたい場合はファイルサイズが0のファイルを自動削除する方法を参照してください。

多段階閾値による条件分岐(小/中/大/特大)

単純なYes/Noでなく、複数のサイズ区分ごとに異なる処理をしたい場合はif / else if を連鎖させます。

サイズ区分ごとに処理を切り替える(4段階)
@echo off
setlocal

set FILEPATH=C:\work\data.csv

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

for %%A in ("%FILEPATH%") do set SIZE=%%~zA

REM サイズ区分の定義
REM 10MB = 10,485,760 bytes
REM  1MB =  1,048,576 bytes
REM 10KB =     10,240 bytes

if %SIZE% EQU 0 (
    echo [EMPTY] 空ファイル - 処理をスキップします
) else if %SIZE% LSS 10240 (
    echo [SMALL] 10KB未満: %SIZE% bytes - 軽量処理を実行
) else if %SIZE% LSS 1048576 (
    echo [MEDIUM] 10KB以上1MB未満: %SIZE% bytes - 通常処理を実行
) else if %SIZE% LSS 10485760 (
    echo [LARGE] 1MB以上10MB未満: %SIZE% bytes - 分割処理を実行
) else (
    echo [XLARGE] 10MB以上: %SIZE% bytes - バックグラウンド処理を実行
)
endlocal
バッチの数値比較は符号付き32bit整数(最大約2.1GB)
set /aif の数値比較はWindows標準で32bit整数です。2GB(2,147,483,647バイト)を超えるファイルを正確に判定する場合はPowerShellの (Get-Item "path").Length を使ってください。

前回サイズと比較してファイルの変化を検知する

「前回実行時より増えた/減った」を検知するには、前回のサイズをテキストファイルに保存しておき、次回実行時に比較します。ログファイルの異常増加・データ欠損の監視に使えます。

前回比較でファイル増加を監視する
@echo off
setlocal

set FILEPATH=C:\logs\app.log
set STATEFILE=C:\work\lastsize.txt
set THRESHOLD=5242880
REM THRESHOLD = 5MB増加したらアラート

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

REM 現在のサイズを取得
for %%A in ("%FILEPATH%") do set CURRENT=%%~zA

REM 前回サイズを読み込む
if exist "%STATEFILE%" (
    set /p PREV=<"%STATEFILE%"
) else (
    set PREV=0
)

REM 増加量を計算
set /a DIFF=%CURRENT% - %PREV%

echo 前回サイズ : %PREV% bytes
echo 現在サイズ : %CURRENT% bytes
echo 増加量     : %DIFF% bytes

REM 5MB以上増加していたらアラート
if %DIFF% GEQ %THRESHOLD% (
    echo [ALERT] ファイルが %DIFF% bytes 増加しました!
)

REM 今回のサイズを記録(次回比較用)
echo %CURRENT% > "%STATEFILE%"
endlocal
set /p で1行目を変数に読み込む
set /p PREV=<"%STATEFILE%" はリダイレクトでファイルの1行目を変数に読み込みます。前回値の保存はこのシンプルな方法で十分です。増加量が負(ファイルが小さくなった)の場合はデータ欠損・上書きのサインなので、if %DIFF% LSS 0 で別途チェックすることも検討してください。

フォルダ内の合計サイズを監視する

フォルダ全体の合計サイズが上限を超えたらアラートを出す、という監視スクリプトを作れます。

フォルダ内合計サイズを計算して閾値チェック
@echo off
setlocal enabledelayedexpansion

set TARGETDIR=C:\logs
set LIMIT=104857600
REM LIMIT = 100MB = 104,857,600 bytes

set TOTAL=0
for %%F in ("%TARGETDIR%\*") do (
    set /a TOTAL+=%%~zF
)

set /a TOTAL_MB=%TOTAL% / 1048576

echo 合計サイズ: %TOTAL% bytes  ^(%TOTAL_MB% MB^)

if %TOTAL% GEQ %LIMIT% (
    echo [WARN] フォルダ容量が %TOTAL_MB% MB に達しました。クリーンアップが必要です。
) else (
    echo [OK] フォルダ容量は問題ありません。
)
endlocal
set /a の積算は2GB超で桁あふれ
set /a TOTAL+=%%~zF の積算も32bit整数制限があります。合計が2GBを超える可能性があるフォルダでは、PowerShellの (Get-ChildItem "path" | Measure-Object -Property Length -Sum).Sum を使って正確な合計を取得してください。

実践パターン①:ログファイルが大きくなったら自動ローテーション

ログファイルが一定サイズを超えたら自動でアーカイブし、新しいログファイルを開始するパターンです。

ログが10MBを超えたらアーカイブ
@echo off
setlocal

set LOGFILE=C:\logs\app.log
set ARCHIVEDIR=C:\logs\archive
set MAX_SIZE=10485760
REM MAX_SIZE = 10MB

REM wmic で日付取得(YYYYMMDD形式)
for /f "tokens=2 delims==" %%A in ('wmic os get LocalDateTime /value') do set DT=%%A
set TODAY=%DT:~0,8%

if not exist "%LOGFILE%" goto :eof

for %%A in ("%LOGFILE%") do set SIZE=%%~zA

if %SIZE% GEQ %MAX_SIZE% (
    echo ログが %SIZE% bytes に達しました。アーカイブを実行します。
    if not exist "%ARCHIVEDIR%" mkdir "%ARCHIVEDIR%"
    REM アーカイブファイル名: app_20250428.log
    move "%LOGFILE%" "%ARCHIVEDIR%\app_%TODAY%.log"
    echo アーカイブ完了: app_%TODAY%.log
)
endlocal
古いアーカイブの自動削除と組み合わせる
ログローテーション全体(世代管理・自動削除)についてはログローテーション完全ガイドを参照してください。

実践パターン②:バックアップ前にディスク空き容量を確認する

バックアップ先のディスク空き容量が不足している場合にコピーを中止することで、中途半端なバックアップによるデータ破損を防げます。

バックアップ前に空き容量をチェック(wmic使用)
@echo off
setlocal

set SRCFILE=C:\work\bigdata.zip
set BACKUPDIR=D:\backup

REM バックアップ元のファイルサイズを取得
if not exist "%SRCFILE%" (
    echo [ERROR] バックアップ元ファイルが見つかりません
    exit /b 1
)
for %%A in ("%SRCFILE%") do set FILESIZE=%%~zA

REM Dドライブの空き容量を wmic で取得(バイト単位)
for /f "tokens=2 delims==" %%A in ('wmic logicaldisk where "DeviceID='D:'" get FreeSpace /value') do (
    set FREESPACE=%%A
)

echo バックアップファイルサイズ : %FILESIZE% bytes
echo Dドライブ空き容量         : %FREESPACE% bytes

REM 空き容量がファイルサイズ以上なら実行
if %FREESPACE% GEQ %FILESIZE% (
    echo [OK] 空き容量十分。バックアップを開始します。
    copy "%SRCFILE%" "%BACKUPDIR%\" > nul
    echo バックアップ完了。
) else (
    echo [ERROR] Dドライブの空き容量が不足しています。バックアップを中止します。
    exit /b 1
)
endlocal
wmic logicaldisk での空き容量取得
wmic logicaldisk where "DeviceID='D:'" get FreeSpace /value でDドライブの空き容量をバイト単位で取得できます。DeviceID のドライブレターを変数化すれば任意のドライブに対応できます。空き容量の比較に set /a を使う場合は2GBの上限に注意し、大容量ドライブではPowerShellを使ってください。

まとめ

ファイルサイズの条件分岐パターンをまとめます。

  • 取得方法: for %%A in ("パス") do set SIZE=%%~zA
  • 前提: if not exist でファイル存在確認してから取得
  • 0バイト検出: if %SIZE% EQU 0 でスキップ・削除・エラー処理
  • 多段階判定: if/else if の連鎖で複数サイズ区分に対応
  • 変化監視: 前回値をファイル保存 → set /p で読み込み → 差分計算
  • フォルダ合計: FOR ループで set /a TOTAL+=%%~zF 積算
  • 2GB超対応: set /a の上限(約2.1GB)を超える場合はPowerShell使用

関連記事: ファイルサイズ取得完全ガイド(%%~zF・単位変換・合計) / ファイルサイズが0のファイルを自動削除する方法 / ファイルの存在チェックと条件分岐の方法

よくある質問(FAQ)

Q%%~zA を使うとファイルサイズが取得できません(変数が空)。
Aファイルが存在しない場合、for ループが実行されず変数がセットされません。if not exist "%FILEPATH%" で存在確認してください。また %%~zA の変数文字は %%A とセットで使うため、for %%F in (...) do set SIZE=%%~zF のように変数文字を統一してください。
Q2GBを超えるファイルのサイズ比較が正しくできません。
Aバッチの数値比較(if)と set /a は32bit整数(最大約2.147GB)の制限があります。2GBを超えるファイルはPowerShellを使用してください:powershell -NoProfile -Command "(Get-Item 'C:\path\file').Length"で正確なバイト数を取得し、条件分岐もPowerShell -Command "if ((Get-Item ...).Length -ge 3GB) {exit 1}"で行うと確実です。
Qネットワーク共有のファイルのサイズを取得したいです。
AUNCパス(\\server\share\file.txt)をそのまま使えます:for %%A in ("\\server\share\file.txt") do set SIZE=%%~zAただしネットワーク状態・権限によっては取得できない場合があります。接続確認として事前に if exist "\\server\share" でアクセス可能かチェックしてください。
QFOR ループ内で IF を使ったら変数が更新されません。
Aバッチの for ループ内で set した変数は、同じブロック内では即時に反映されません。setlocal enabledelayedexpansion を宣言し、%VAR% の代わりに !VAR!(遅延展開)で参照してください。これは for ループ内の set /a TOTAL+= での積算でも同様に必要です。
Qサブフォルダも含めた再帰的な合計サイズを取得したいです。
Afor /r を使うと再帰的にファイルを処理できます:for /r "%TARGETDIR%" %%F in (*) do set /a TOTAL+=%%~zFただし2GBを超える合計は正確に計算できません。PowerShellの (Get-ChildItem -Recurse "path" | Measure-Object -Property Length -Sum).Sumが2GB超でも正確に合計を返します。