「ファイルが最後にいつ更新されたか確認したい」「更新日時を変数に入れて古ければ処理を実行したい」——バッチファイルでファイルの更新日時を扱う場面は多くあります。本記事では、最もシンプルな %%~tF 修飾子から for /f・wmic・PowerShell 連携まで4つの方法を比較し、日時比較・条件分岐・変更検知などの実践パターンを体系的に解説します。
%%~tFでファイルの更新日時を1行で取得する方法for /f + dirで日付・時刻を分割して変数に格納する方法- PowerShell で秒単位・ミリ秒単位の精度で日時を取得する方法
- 取得した日時を使って「N日以上古いか」を判定する方法
- ファイルの更新日時が変わったことを検知して処理を実行する方法
- 複数ファイルの更新日時一覧を CSV に出力する方法
取得方法の比較
| 方法 | 取得日時の種類 | 精度 | ロケール依存 | 特徴 |
|---|---|---|---|---|
%%~tF 修飾子 |
最終更新日時 | 分単位 | △ あり | 最もシンプル・1行で取得 |
for /f + dir /tw |
最終更新日時 | 分単位 | △ あり | 日付・時刻を別変数に分割しやすい |
for /f + dir /tc |
作成日時 | 分単位 | △ あり | 作成日時が必要な場合に使用 |
wmic datafile |
作成・更新・アクセス | 秒単位 | ○ 少ない | Windows 11 22H2以降非推奨 |
PowerShell Get-Item |
作成・更新・アクセス | ミリ秒単位 | ◎ 指定可能 | 最も柔軟・将来性あり |
dir /tw = 最終書き込み日時(最終更新日時・デフォルト)dir /tc = 作成日時(Creation time)dir /ta = 最終アクセス日時(Access time)更新日時を取得したい場合は
/tw(またはオプションなし)を使います。
方法1: %%~tF 修飾子(最もシンプル)
FOR 変数に %%~tF 修飾子を使うと、ファイルの最終更新日時を1行で取得できます。最も短く書けるため、日時の確認や表示が目的の場合に最適です。
基本: 1ファイルの更新日時を表示
@echo off
setlocal
set TARGET=C:workdata.log
for %%F in ("%TARGET%") do (
echo ファイル名: %%~nxF
echo 更新日時 : %%~tF
echo サイズ : %%~zF バイト
)
endlocal
更新日時を変数に格納する
@echo off
setlocal
set TARGET=C:workdata.log
rem %%~tF の値を変数に格納(例: 2025/05/11 14:32)
for %%F in ("%TARGET%") do set FILE_DT=%%~tF
echo 更新日時: %FILE_DT%
endlocal
%%~tF で取得できるその他の日時修飾子
@echo off
setlocal
set TARGET=C:workdata.log
rem FOR 変数修飾子の一覧(%%F にパスが入っている前提)
for %%F in ("%TARGET%") do (
echo フルパス : %%~fF
echo ドライブ : %%~dF
echo ディレクトリ: %%~pF
echo ファイル名: %%~nF
echo 拡張子 : %%~xF
echo サイズ : %%~zF
echo 更新日時 : %%~tF
echo 属性 : %%~aF
)
endlocal
日本語環境では通常
2025/05/11 14:32 形式ですが、英語環境では 05/11/2025 2:32 PM のように形式が変わります。日時の文字列比較をする場合はロケールに依存しない PowerShell や wmic の利用を検討してください。
方法2: for /f + dir で日付・時刻を分割取得
dir の出力を for /f で解析して日付と時刻を別々の変数に格納します。日付部分や時刻部分を個別に使いたい場合に便利です。
最終更新日時(日付・時刻を別変数に格納)
@echo off
setlocal
set TARGET=C:workdata.log
rem dir /tw の出力例(日本語環境):
rem 2025/05/11 14:32 1,234 data.log
rem tokens=1,2 で 日付=%%A, 時刻=%%B に格納
for /f "tokens=1,2" %%A in ('dir /tw /b /4 "%TARGET%" 2^>nul ^| findstr /r "[0-9]"') do (
set FILE_DATE=%%A
set FILE_TIME=%%B
goto :got
)
:got
echo 更新日付: %FILE_DATE%
echo 更新時刻: %FILE_TIME%
endlocal
dir の詳細出力から tokens を正確に取り出す
@echo off
setlocal
set TARGET=C:workdata.log
rem dir /tw(/4 = 4桁年)の標準出力例:
rem 2025/05/11 14:32 1,234 data.log
rem tokens=1 = 日付, tokens=2 = 時刻
for /f "tokens=1,2 delims= " %%A in ('dir "%TARGET%" /tw /4 2^>nul ^| findstr /r "[0-9][0-9][0-9][0-9]/"') do (
set FDATE=%%A
set FTIME=%%B
goto :done
)
:done
echo 日付: %FDATE%
echo 時刻: %FTIME%
endlocal
方法3: wmic で秒単位の日時を取得
wmic datafile を使うと、秒単位の正確な日時を取得できます。ロケール依存が少なく、作成日時・更新日時・アクセス日時を全て取得できます。
@echo off
setlocal
rem ※ wmic はパスに (バックスラッシュ) を \ に変換して指定する必要がある
rem ※ Windows 11 22H2 以降では wmic は非推奨。PowerShell を推奨
set TARGET=C:\work\data.log
rem LastModified を取得(形式: 20250511143225.000000+540)
for /f "tokens=2 delims==" %%A in ('wmic datafile where "name='%TARGET%'" get LastModified /value 2^>nul') do (
set RAW_DT=%%A
goto :got_wmic
)
:got_wmic
rem 年月日時分秒を切り出す(YYYYMMDDHHmmSS 形式)
set DT_YEAR=%RAW_DT:~0,4%
set DT_MON=%RAW_DT:~4,2%
set DT_DAY=%RAW_DT:~6,2%
set DT_HOUR=%RAW_DT:~8,2%
set DT_MIN=%RAW_DT:~10,2%
set DT_SEC=%RAW_DT:~12,2%
echo 更新日時: %DT_YEAR%/%DT_MON%/%DT_DAY% %DT_HOUR%:%DT_MIN%:%DT_SEC%
endlocal
wmic コマンドは Windows 11 22H2 以降で非推奨(deprecated)となり、将来的に削除される予定です。新規スクリプトでは後述の PowerShell を使うことを推奨します。
方法4: PowerShell で正確な日時を取得(推奨)
PowerShell の Get-Item を使うと、ロケールに依存せず、秒・ミリ秒単位の精度で日時を取得できます。
更新日時を取得してバッチ変数に格納
@echo off
setlocal
set TARGET=C:workdata.log
rem PowerShell で更新日時を取得して一時ファイル経由でバッチ変数に格納
powershell -NoProfile -Command "(Get-Item '%TARGET%').LastWriteTime.ToString('yyyy/MM/dd HH:mm:ss')" > "%TEMP%file_dt.txt"
set /p FILE_DT= < "%TEMP%file_dt.txt"
echo 更新日時: %FILE_DT%
endlocal
作成日時・更新日時・アクセス日時を全て取得
@echo off
setlocal
set TARGET=C:workdata.log
powershell -NoProfile -Command ^
"$f = Get-Item '%TARGET%';" ^
"Write-Output ('CREATED=' + $f.CreationTime.ToString('yyyy/MM/dd HH:mm:ss'));" ^
"Write-Output ('MODIFIED=' + $f.LastWriteTime.ToString('yyyy/MM/dd HH:mm:ss'));" ^
"Write-Output ('ACCESSED=' + $f.LastAccessTime.ToString('yyyy/MM/dd HH:mm:ss'))" ^
> "%TEMP%file_times.txt"
for /f "tokens=1,* delims==" %%K in (%TEMP%file_times.txt) do set %%K=%%L
echo 作成日時 : %CREATED%
echo 更新日時 : %MODIFIED%
echo アクセス日時: %ACCESSED%
endlocal
PowerShell との連携パターン詳細は PowerShellをバッチファイルから呼び出す方法 を参照してください。
実践例A: 更新日時で「N日以上古いか」を判定する
ファイルが指定日数以上更新されていない場合に警告・処理を実行するパターンです。
@echo off
setlocal
set TARGET=C:workdata.log
set THRESHOLD_DAYS=7
rem PowerShell でファイルが N日以上古いか判定(1=古い, 0=新しい)
powershell -NoProfile -Command ^
"$f = Get-Item '%TARGET%';" ^
"$days = ((Get-Date) - $f.LastWriteTime).Days;" ^
"Write-Output ('DAYS_OLD=' + $days);" ^
"if ($days -ge %THRESHOLD_DAYS%) { Write-Output 'OLD=1' } else { Write-Output 'OLD=0' }" ^
> "%TEMP%age_check.txt"
for /f "tokens=1,* delims==" %%K in (%TEMP%age_check.txt) do set %%K=%%L
echo ファイルの経過日数: %DAYS_OLD% 日
if "%OLD%"=="1" (
echo [WARNING] %TARGET% は %THRESHOLD_DAYS% 日以上更新されていません
rem 古いファイルへの処理をここに記述
) else (
echo [OK] %TARGET% は %THRESHOLD_DAYS% 日以内に更新されています
)
endlocal
実践例B: 更新日時を比較して新しい方のファイルを特定する
@echo off
setlocal
set FILE1=C:workdata.log
set FILE2=C:workapp.log
rem PowerShell で2ファイルの更新日時を比較
powershell -NoProfile -Command ^
"$f1 = Get-Item '%FILE1%';" ^
"$f2 = Get-Item '%FILE2%';" ^
"if ($f1.LastWriteTime -gt $f2.LastWriteTime) { Write-Output 'NEWER=FILE1' }" ^
"elseif ($f2.LastWriteTime -gt $f1.LastWriteTime) { Write-Output 'NEWER=FILE2' }" ^
"else { Write-Output 'NEWER=SAME' }" ^
> "%TEMP%compare.txt"
for /f "tokens=1,* delims==" %%K in (%TEMP%compare.txt) do set %%K=%%L
if "%NEWER%"=="FILE1" echo %FILE1% の方が新しい
if "%NEWER%"=="FILE2" echo %FILE2% の方が新しい
if "%NEWER%"=="SAME" echo 2つのファイルの更新日時は同じ
endlocal
実践例C: フォルダ内の全ファイルの更新日時一覧をCSVに出力
@echo off
setlocal
set SRCDIR=C:work
set CSVOUT=C:work imestamps.csv
rem CSVヘッダー
echo ファイル名,更新日時,サイズ(bytes) > "%CSVOUT%"
for %%F in ("%SRCDIR%*.*") do (
echo %%~nxF,%%~tF,%%~zF >> "%CSVOUT%"
)
echo CSV 出力完了: %CSVOUT%
endlocal
実践例D: ファイルの更新を監視して変更を検知する
前回の更新日時を記録しておき、次回実行時に変わっていたら処理を実行するパターンです。
@echo off
setlocal
set TARGET=C:workdata.log
set STAMP_FILE=%~dp0last_modified.txt
rem 現在の更新日時を取得
powershell -NoProfile -Command "(Get-Item '%TARGET%').LastWriteTime.ToString('yyyyMMddHHmmss')" > "%TEMP%cur_dt.txt"
set /p CUR_DT= < "%TEMP%cur_dt.txt"
rem 前回の更新日時を読み込む(初回は空)
set PREV_DT=
if exist "%STAMP_FILE%" set /p PREV_DT= < "%STAMP_FILE%"
if "%CUR_DT%"=="%PREV_DT%" (
echo [NO CHANGE] ファイルは変更されていません
) else (
echo [CHANGED] ファイルが更新されました: %CUR_DT% (前回: %PREV_DT%)
rem ここに変更時の処理を記述(コピー・通知・ログなど)
rem 新しい更新日時を記録
echo %CUR_DT% > "%STAMP_FILE%"
)
endlocal
実践例E: 更新日時をファイル名に付けてバックアップする
@echo off
setlocal
set TARGET=C:workdata.log
rem %%~tF から日時を取得(例: 2025/05/11 14:32 → 20250511_1432)
for %%F in ("%TARGET%") do set RAW_DT=%%~tF
rem 日時文字列を整形(/ : スペースを除去)
set DT=%RAW_DT:/=%
set DT=%DT: =_%
set DT=%DT::=%
rem バックアップ先ファイル名を構築
for %%F in ("%TARGET%") do set BACKUP=%%~dpF%%~nF_%DT%%%~xF
copy "%TARGET%" "%BACKUP%"
echo バックアップ完了: %BACKUP%
endlocal
よくある落とし穴
落とし穴1: %%~tF の形式は環境によって異なる
rem 日本語環境: 2025/05/11 14:32
rem 英語環境: 05/11/2025 2:32 PM
rem その他環境: 11.05.2025 14:32
rem 環境に依存しない方法が必要な場合は PowerShell で形式を明示指定する
powershell -NoProfile -Command "(Get-Item 'C:workdata.log').LastWriteTime.ToString('yyyy/MM/dd HH:mm:ss')"
落とし穴2: dir /tc は「作成日時」で「更新日時」ではない
rem NG: /tc は作成日時(ファイルを最初に作ったときの日時) dir /tc "%TARGET%" rem OK: 更新日時が必要なら /tw(または /t のみ)を使う dir /tw "%TARGET%" rem dir のデフォルト(/t なし)も更新日時を表示する
落とし穴3: ファイルが存在しない場合の処理を忘れる
rem for %%F in ("存在しないファイル") do set DT=%%~tF
rem → %%~tF は空文字列になる(エラーにはならない)
rem 存在確認してから取得する
set TARGET=C:workdata.log
if not exist "%TARGET%" (
echo [ERROR] ファイルが存在しません: %TARGET%
exit /b 1
)
for %%F in ("%TARGET%") do set DT=%%~tF
echo 更新日時: %DT%
落とし穴4: ループ内で %%~tF を使う場合の変数スコープ
rem NG: for ブロック内で %DT% を参照すると古い値になる
setlocal
for %%F in (C:work*.log) do (
set DT=%%~tF
echo %DT% ← 常に同じ値(最初のファイルの日時)になる
)
rem OK: enabledelayedexpansion を使い !DT! で参照
setlocal enabledelayedexpansion
for %%F in (C:work*.log) do (
set DT=%%~tF
echo !DT! ← 各ファイルの日時が正しく表示される
)
遅延展開の詳細は setlocal enabledelayedexpansion 完全ガイド を参照してください。
落とし穴5: 英語環境での AM/PM 形式への対応
rem 英語環境では %%~tF が "05/11/2025 2:32 PM" のように AM/PM 形式になる
rem dir /tw の出力も同様に変わる
rem 環境を問わず一定の形式を保証したい場合は PowerShell を使う
powershell -NoProfile -Command "(Get-Item '%TARGET%').LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss')"
よくある質問(FAQ)
dir /o:-d /b(更新日時の新しい順)の先頭行が最新ファイルです。
@echo off
setlocal
set SRCDIR=C:work
rem 更新日時が最新のファイルを取得
for /f "delims=" %%F in ('dir /b /a-d /o:-d "%SRCDIR%*"') do (
echo 最新ファイル: %%F
echo 更新日時: %%~tF
goto :found
)
:found
endlocal
最新ファイル取得の詳細は 指定フォルダ配下の最新更新ファイルを取得する方法 を参照してください。
PowerShell で今日の日付と比較するのが確実です。
@echo off
setlocal
set TARGET=C:workdata.log
powershell -NoProfile -Command ^
"$f = Get-Item '%TARGET%';" ^
"$isToday = ($f.LastWriteTime.Date -eq (Get-Date).Date);" ^
"if ($isToday) { Write-Output 'TODAY=1' } else { Write-Output 'TODAY=0' }" ^
> "%TEMP% oday_check.txt"
for /f "tokens=1,* delims==" %%K in (%TEMP% oday_check.txt) do set %%K=%%L
if "%TODAY%"=="1" (
echo [OK] 今日更新されたファイルです
) else (
echo [INFO] 今日以外に更新されたファイルです
)
endlocal
PowerShell で fff フォーマットを指定するとミリ秒まで取得できます。
powershell -NoProfile -Command "(Get-Item 'C:workdata.log').LastWriteTime.ToString('yyyy/MM/dd HH:mm:ss.fff')"
PowerShell で LastWriteTime プロパティに代入します。
rem 更新日時を現在日時に更新(touch 相当) powershell -NoProfile -Command "(Get-Item 'C:workdata.log').LastWriteTime = Get-Date" rem 任意の日時に設定 powershell -NoProfile -Command "(Get-Item 'C:workdata.log').LastWriteTime = '2025-01-15 09:00:00'"
dir /o:d(更新日時の古い順)または /o:-d(新しい順)で並べ替えてループします。
@echo off
setlocal
set SRCDIR=C:work
echo === 更新日時の古い順 ===
for /f "delims=" %%F in ('dir /b /a-d /o:d "%SRCDIR%*.log"') do (
echo %%~tF %%F
)
endlocal
まとめ
| 目的 | 推奨方法 |
|---|---|
| 更新日時を1行で表示・取得 | for %%F in ("file") do echo %%~tF |
| 日付・時刻を別変数に格納 | for /f + dir /tw |
| ロケール非依存で正確に取得 | PowerShell (Get-Item).LastWriteTime.ToString('形式') |
| 作成日時も取得したい | PowerShell .CreationTime または dir /tc |
| N日以上古いか判定 | PowerShell で (Get-Date) - LastWriteTime).Days |
| 今日更新されたか判定 | PowerShell で .LastWriteTime.Date -eq (Get-Date).Date |
| ファイルの変更を検知 | 更新日時をファイルに保存して前回と比較 |
| 更新日時を名前に付けてバックアップ | %%~tF を整形してファイル名に組み込む |
ファイルサイズの取得・条件分岐については バッチファイルでファイルサイズを取得して条件分岐する方法 を、最新ファイルの取得については 指定フォルダ配下の最新更新ファイルを取得する方法 も合わせて参照してください。