N日より古いファイルを削除するバッチファイル


677

バッチファイルで7日以上経過したすべてのファイルを削除する方法を探しています。私はWebを検索しましたが、数百行のコードを含む例や、タスクを実行するために追加のコマンドラインユーティリティをインストールする必要がある例を見つけました。

BASHでも、数行のコードで同様のことができます。Windowsでは、バッチファイルに対して少なくともリモートで簡単なことができるようです。追加のユーティリティを使用せずに、標準のWindowsコマンドプロンプトで機能するソリューションを探しています。PowerShellもCygwinも使用しないでください。


8
Jeff AtwoodはServerfaultについてこれに答えました。serverfault.com/questions/49614/delete-files-older-than-x-days
Dusty

内部CMD.EXEコマンドを使用します.BATファイルに基づいて、新しいメソッドは、ここに掲載されています:stackoverflow.com/questions/9746778/...
Aaciniを

1
gehrcke.de/timegapsは、この目的のために設計されています。それはより洗練された削除スキームも可能にします:過去7日間のファイルを保持することに加えて、例えば過去8週間、12ヶ月、2年間のそれぞれについて1つのファイルを保持することも可能にします。
Jan-Philip Gehrcke博士、2014年

回答:


1071

楽しい:

forfiles -p "C:\what\ever" -s -m *.* -d <number of days> -c "cmd /c del @path"

詳細については、forfilesドキュメントを参照してください。

その他の利点については、Windows XPコマンドラインのAZインデックスを参照してください。

forfilesマシンにインストールしていない場合は、Windows Server 2003からWindows XPマシンにコピーします%WinDir%\system32\。EXEはWindows Server 2003とWindows XPの間で完全に互換性があるため、これは可能です。

それ以降のバージョンのWindowsおよびWindows Serverでは、デフォルトでインストールされています。

Windows 7以降(Windows 10を含む)の場合:

構文が少し変更されました。したがって、更新されたコマンドは次のとおりです。

forfiles /p "C:\what\ever" /s /m *.* /D -<number of days> /C "cmd /c del @path"

12
デルの@FILEである必要があります。大文字と小文字の区別も必要です。テストには/ c echo @FILEを使用することをお勧めします
Russell Steen

40
@Russell:@PATHは名前を含むフルパスです。@FILEは名前にすぎないので、サブフォルダを扱っている場合は機能しません。
gregmac

86
10日より古いファイルが必要な場合は、-d "-10"を指定する必要があることに注意してください。-veは「より古い」を意味し、+ veは「より新しい」を意味します。-dのパラメーターとして、DDMMYYまたは-DDMMYY形式を指定することもできます。
gregmac

42
Win Server 2008でこの構文を使用しました:forfiles / P "C:\ Mysql_backup" / S / M * .sql / D -30 / C "cmd / c del @PATH"
jman

9
この回答は、「7日より前に作成」ではなく「7日より前に変更」として定義されている場合に機能します。後者はどのようにして達成できますか?
TimS 2013年

76

次のコマンドを実行します

ROBOCOPY C:\source C:\destination /mov /minage:7
del C:\destination /q

robocopyを介してすべてのファイルを(ファイルを移動してから削除する/ movとは対照的に/ movを使用して)すべてのファイルを別の場所に移動し、そのパスで削除コマンドを実行すると、すべての良い。

また、大量のデータを含むディレクトリがある場合は、/mirスイッチを使用できます


5
ほとんどの場合、これはかなり非現実的な答えです。大量のデータが含まれているディレクトリがある場合、うまく機能しません。私はそれを「その場で」行う答えの1つに行きます
adamb0mb 2013年

5
@ adamb0mbこれは実際的ではありません。「destination」「source」と同じファイルシステムにある場合、移動操作は非常に軽量です。robocopyは非常に堅牢であるため、実際には、任意のディレクトリサイズ、あいまいなファイル名、基本的に任意のパス長、および必要に応じてディレクトリを含めて機能します。他の多くのWindowsユーティリティについては確かに言えません。ファイル名に問題があると予想される場合rd /s /q c:\destinationは、delコマンドの代わりに使用するか、別のrobocopy /mir c:\emptydir c:\destination実行を使用してディレクトリを空にします。
syneticon-dj 2013

12
さらに、robocopyはUNCパスをサポートします- forfiles受け入れられた回答からはUNCパスはサポートしません。
syneticon-dj 2013

3
「自分のファイルはすでに欲しいところにあります。それらを移動する必要はありません。」「ファイルを削除することは論理的にはあなたがやっていることなので、そうしてください
。Robocopyに

3
C:\test7日以上経過したすべてのファイルを表示するには、このワンライナーをお勧めします。ファイルを削除するには、変更echoするdelforfiles /p "C:\test" /m "*.*" /c "cmd /c echo @file" /D -7
パワーユーザー

25

OKは少し飽きて、これを思いつきました。これには、毎日使用するために制限された、私のバージョンの貧しい人のLinuxエポックの置き換えが含まれています(時間の保持なし):

7daysclean.cmd

@echo off
setlocal ENABLEDELAYEDEXPANSION
set day=86400
set /a year=day*365
set /a strip=day*7
set dSource=C:\temp

call :epoch %date%
set /a slice=epoch-strip

for /f "delims=" %%f in ('dir /a-d-h-s /b /s %dSource%') do (
    call :epoch %%~tf
    if !epoch! LEQ %slice% (echo DELETE %%f ^(%%~tf^)) ELSE echo keep %%f ^(%%~tf^)
)
exit /b 0

rem Args[1]: Year-Month-Day
:epoch
    setlocal ENABLEDELAYEDEXPANSION
    for /f "tokens=1,2,3 delims=-" %%d in ('echo %1') do set Years=%%d& set Months=%%e& set Days=%%f
    if "!Months:~0,1!"=="0" set Months=!Months:~1,1!
    if "!Days:~0,1!"=="0" set Days=!Days:~1,1!
    set /a Days=Days*day
    set /a _months=0
    set i=1&& for %%m in (31 28 31 30 31 30 31 31 30 31 30 31) do if !i! LSS !Months! (set /a _months=!_months! + %%m*day&& set /a i+=1)
    set /a Months=!_months!
    set /a Years=(Years-1970)*year
    set /a Epoch=Years+Months+Days
    endlocal& set Epoch=%Epoch%
    exit /b 0

使用法

set /a strip=day*7:保持する日数を7に変更します。

set dSource=C:\temp :これは、ファイルをチェックするための開始ディレクトリです。

ノート

これは非破壊的なコードであり、何が起こったかを表示します。

変化する :

if !epoch! LEQ %slice% (echo DELETE %%f ^(%%~tf^)) ELSE echo keep %%f ^(%%~tf^)

のようなものに:

if !epoch! LEQ %slice% del /f %%f

ファイルは実際に削除されます

2月:28日間にハードコーディングされています。両性具有年は本当に追加するのは地獄です。誰かが10行のコードを追加しないというアイデアを持っている場合は、先に進んで投稿して、コードに追加します。

epoch:特定の日付より古いファイルを削除する必要があるため、時間を考慮しませんでした。時間/分を使用すると、保存する予定の日からファイルが削除されます。

制限

エポックは、短い日付形式がYYYY-MM-DDであることを当然と見なしています。他の設定またはランタイム評価に適合させる必要があります(sShortTime、ユーザーバインド構成を読み取り、フィルターで適切なフィールド順序を構成し、フィルターを使用して引数から正しいデータを抽出します)。

このエディタの自動フォーマットが嫌いだと言ったことはありますか?空白行が削除され、コピーと貼り付けは地獄です。

これがお役に立てば幸いです。


4
非破壊的なコードの+1は、自分でコード例を提供するときに心に留めておきます。
Haugholt、2014

5
かなり遅れて完全に無関係ですが7daysclean.cmd、シンセパンクバンドの素晴らしい名前のように聞こえます。
Flonk

21
forfiles /p "v:" /s /m *.* /d -3 /c "cmd /c del @path"

/d -3(3日前)する必要があります。そのため、複雑なバッチはすべてゴミ箱に入れることができます。またforfiles、UNCパスをサポートしていないため、特定のドライブにネットワーク接続します。


3
他の回答と同じエラー(承認されたものを含む)。指定するこの奇妙な習慣はどこ*.*から来たのですか?ワイルドカード*.*はWindowsのすべてのファイルと一致しません。.名前が一致するファイルのみを照合します。OPは.、ファイル名に要求することについて何も述べていません。適切なパラメータはですが/M *、これがデフォルトです。まったく必要はありません/M
AnT 2015年

@AnT:よろしいですか?Windowsと*.*まったく同じよう*に動作すると思います。実際、私は自分のコンピューターで試してみましたが、dir *.*実際にはtest file、拡張子のないファイルが表示されていました。
Andreas Rejbrand 2018年

1
@Andreas Rejbrand:私も驚くべきことだと思いますが*.*dirとの-mオプションの扱いが一致していませんforfiles-m *.*私は(それを自分で試してください)上記の私のコメントで述べたように、マスクは確かに、拡張子のファイル名をスキップします。ここで面白いのは、MSのドキュメントにそれ-m *.*がデフォルトであることを明示的に述べていることです。ただし、実際に試してみると、デフォルトが実際にあることがわかり-m *ます。すべてのファイルが反復されます。
AnT 2018年

1
このMSのドキュメントページ- technet.microsoft.com/en-us/library/cc753551(v=ws.11).aspxは-ドキュメントの作者が間違っていると信じているため(例では例えば)大量のエラーが含まれている*.*マスクが適用されますすべてのファイルに。「この奇妙な習慣」についての私のrethorical質問は治療以来、実にため差し出がましいだった*.**同等のものとして長年Windowsの規則はあります。ただし、/mオプションはforfiles何らかの理由でその規則に違反しています。
AnT、

1
上の背景5:Windowsでワイルドカードblogs.msdn.microsoft.com/jeremykuhne/2017/06/04/...
MSalters

18

同様の質問に対する私の答えを見てください:

REM del_old.bat
REM usage: del_old MM-DD-YYY
for /f "tokens=*" %%a IN ('xcopy *.* /d:%1 /L /I null') do if exist %%~nxa echo %%~nxa >> FILES_TO_KEEP.TXT
for /f "tokens=*" %%a IN ('xcopy *.* /L /I /EXCLUDE:FILES_TO_KEEP.TXT null') do if exist "%%~nxa" del "%%~nxa"

これにより、特定の日付より古いファイルが削除されます。きっと現在の日付から7日遡って修正できると思います。

更新:上記のスクリプトでHerbCSOが改善されていることに気づきました。代わりに彼のバージョンを使用することをお勧めします。


12

私のコマンドは

forfiles -p "d:\logs" -s -m*.log -d-15 -c"cmd /c del @PATH\@FILE" 

@PATH -私の場合は単なるパスなので、使用する必要がありました @PATH\@FILE

またforfiles /?、私にとってもうまくいきませんでしたがforfiles( "?"なしで)うまくいきました。

そして、私が持っている唯一の質問:複数のマスクを追加する方法(たとえば、「. log | .bak」)?

ここでダウンロードした forfiles.exeに関するすべて(Win XPの場合)

ただし、Windowsサーバーを使用している場合は、forfiles.exeがすでに存在している必要があり、ftpバージョンとは異なります。そのため、コマンドを変更する必要があります。

Windows Server 2003では、次のコマンドを使用しています。

forfiles -p "d:\Backup" -s -m *.log -d -15 -c "cmd /c del @PATH"

9

多くの場合、バッチファイルを使用して解決する相対的な日付/時刻関連の質問があります。ただし、コマンドラインインタープリターcmd.exeには、日付/時刻の計算機能はありません。追加のコンソールアプリケーションまたはスクリプトを使用した多くの優れたソリューションが、Stack Overflowの他のページや他のWebサイトに既に投稿されています。

日付/時刻に基づく操作に共通するのは、日付/時刻文字列を特定の日からの秒数に変換する必要があることです。1970-01-01 00:00:00 UTCが非常に一般的です。ただし、特定のタスクをサポートするために必要な日付範囲に応じて、後日も使用できます。

Jayは、コマンドラインインタープリターcmd.exeの高速な「日付から秒」ソリューションを含む7daysclean.cmdを投稿しました。ただし、うるう年は考慮されません。JRは、現在の年のうるう日を考慮に入れるアドオンを投稿しましたが、基準年、つまり1970年以降の他のうるう年は無視しています。

C / C ++で作成されたアプリケーションの日付/時刻変換関数で、1970-01-01からのうるう日を含む日数をすばやく取得するために、小さなC関数で一度作成された20年の静的テーブル(配列)を使用します。

この非常に高速なテーブルメソッドは、FORコマンドを使用するバッチコードでも使用できます。そこでGetSeconds、このルーチンに渡される日付/時刻文字列の1970-01-01 00:00:00 UTC以降の秒数を計算するバッチサブルーチンをコーディングすることにしました。

注: Windowsファイルシステムもうるう秒をサポートしていないため、うるう秒は考慮されません。

まず、テーブル:

  1. うるう日を含む各年の1970-01-01 00:00:00 UTC以降の日数。

    1970 - 1979:     0   365   730  1096  1461  1826  2191  2557  2922  3287
    1980 - 1989:  3652  4018  4383  4748  5113  5479  5844  6209  6574  6940
    1990 - 1999:  7305  7670  8035  8401  8766  9131  9496  9862 10227 10592
    2000 - 2009: 10957 11323 11688 12053 12418 12784 13149 13514 13879 14245
    2010 - 2019: 14610 14975 15340 15706 16071 16436 16801 17167 17532 17897
    2020 - 2029: 18262 18628 18993 19358 19723 20089 20454 20819 21184 21550
    2030 - 2039: 21915 22280 22645 23011 23376 23741 24106 24472 24837 25202
    2040 - 2049: 25567 25933 26298 26663 27028 27394 27759 28124 28489 28855
    2050 - 2059: 29220 29585 29950 30316 30681 31046 31411 31777 32142 32507
    2060 - 2069: 32872 33238 33603 33968 34333 34699 35064 35429 35794 36160
    2070 - 2079: 36525 36890 37255 37621 37986 38351 38716 39082 39447 39812
    2080 - 2089: 40177 40543 40908 41273 41638 42004 42369 42734 43099 43465
    2090 - 2099: 43830 44195 44560 44926 45291 45656 46021 46387 46752 47117
    2100 - 2106: 47482 47847 48212 48577 48942 49308 49673
    

    1970-01-01から始まるエポックで2039年から2106年までの秒を計算することは、C / C ++で符号なし32ビット変数、つまり符号なしlong(または符号なしint)を使用した場合にのみ可能です。

    しかし、cmd.exeは数式に符号付き32ビット変数を使用します。したがって、最大値は2147483647(0x7FFFFFFF)であり、2038-01-19 03:14:07です。

  2. 1970年から2106年までのうるう年情報(いいえ/はい)。

    1970 - 1989: N N Y N N N Y N N N Y N N N Y N N N Y N
    1990 - 2009: N N Y N N N Y N N N Y N N N Y N N N Y N
    2010 - 2029: N N Y N N N Y N N N Y N N N Y N N N Y N
    2030 - 2049: N N Y N N N Y N N N Y N N N Y N N N Y N
    2050 - 2069: N N Y N N N Y N N N Y N N N Y N N N Y N
    2070 - 2089: N N Y N N N Y N N N Y N N N Y N N N Y N
    2090 - 2106: N N Y N N N Y N N N N N N N Y N N
                                     ^ year 2100
    
  3. 現在の年の各月の最初の日までの日数。

                       Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
    Year with 365 days:  0  31  59  90 120 151 181 212 243 273 304 334
    Year with 366 days:  0  31  60  91 121 152 182 213 244 274 305 335
    

1970-01-01以降の日付を秒数に変換するのは、これらのテーブルを使用すると非常に簡単です。

ご注目下さい!

日付と時刻の文字列の形式は、Windowsの地域と言語の設定によって異なります。区切り文字と環境変数に割り当てられたトークンの順序DayMonthおよびYear最初のFORループでGetSecondsは、必要に応じてローカルの日付/時刻形式に適合させる必要があります。

環境変数の日付形式場合は、環境変数の日付文字列を適応させることが必要であるDATEは、コマンドで使用される日付形式と異なるのため%%~tF

例えばとき%DATE%に展開Sun 02/08/2015しつつ%%~tFに展開02/08/2015 07:38 PM以下のコードは、ライン4を修正して使用することができます。

call :GetSeconds "%DATE:~4% %TIME%"

これにより、サブルーチンに渡され02/08/2015ます-曜日の省略形の3文字と分離スペース文字のない日付文字列。

または、以下を使用して現在の日付を正しい形式で渡すことができます。

call :GetSeconds "%DATE:~-10% %TIME%"

日付文字列の最後の10文字が関数に渡されるようにGetSecondsなりました。したがって、環境変数DATEの日付文字列に平日があってもなくても、日と月が常に2桁の期待どおりの順序であるdd/mm/yyyy かどうか、つまり形式またはは問題ではありませんdd.mm.yyyy

これは、削除するファイルとC:\Tempフォルダツリーに保持するファイルを出力するコメントを説明するバッチコードです。最初のFORループのコードを参照してください。

@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem Get seconds since 1970-01-01 for current date and time.
call :GetSeconds "%DATE% %TIME%"
rem Subtract seconds for 7 days from seconds value.
set /A "LastWeek=Seconds-7*86400"

rem For each file in each subdirectory of C:\Temp get last modification date
rem (without seconds -> append second 0) and determine the number of seconds
rem since 1970-01-01 for this date/time. The file can be deleted if seconds
rem value is lower than the value calculated above.

for /F "delims=" %%F in ('dir /A-D-H-S /B /S "C:\Temp"') do (
    call :GetSeconds "%%~tF:0"
    rem if !Seconds! LSS %LastWeek% del /F "%%~fF"
    if !Seconds! LEQ %LastWeek% (
        echo Delete "%%~fF"
    ) else (
        echo Keep   "%%~fF"
    )
)
endlocal
goto :EOF


rem No validation is made for best performance. So make sure that date
rem and hour in string is in a format supported by the code below like
rem MM/DD/YYYY hh:mm:ss or M/D/YYYY h:m:s for English US date/time.

:GetSeconds

rem If there is " AM" or " PM" in time string because of using 12 hour
rem time format, remove those 2 strings and in case of " PM" remember
rem that 12 hours must be added to the hour depending on hour value.

set "DateTime=%~1"
set "Add12Hours=0"
if "%DateTime: AM=%" NEQ "%DateTime%" (
    set "DateTime=%DateTime: AM=%"
) else if "%DateTime: PM=%" NEQ "%DateTime%" (
    set "DateTime=%DateTime: PM=%"
    set "Add12Hours=1"
)

rem Get year, month, day, hour, minute and second from first parameter.

for /F "tokens=1-6 delims=,-./: " %%A in ("%DateTime%") do (
    rem For English US date MM/DD/YYYY or M/D/YYYY
    set "Day=%%B" & set "Month=%%A" & set "Year=%%C"
    rem For German date DD.MM.YYYY or English UK date DD/MM/YYYY
    rem set "Day=%%A" & set "Month=%%B" & set "Year=%%C"
    set "Hour=%%D" & set "Minute=%%E" & set "Second=%%F"
)
rem echo Date/time is: %Year%-%Month%-%Day% %Hour%:%Minute%:%Second%

rem Remove leading zeros from the date/time values or calculation could be wrong.
if "%Month:~0,1%"  EQU "0" ( if "%Month:~1%"  NEQ "" set "Month=%Month:~1%"   )
if "%Day:~0,1%"    EQU "0" ( if "%Day:~1%"    NEQ "" set "Day=%Day:~1%"       )
if "%Hour:~0,1%"   EQU "0" ( if "%Hour:~1%"   NEQ "" set "Hour=%Hour:~1%"     )
if "%Minute:~0,1%" EQU "0" ( if "%Minute:~1%" NEQ "" set "Minute=%Minute:~1%" )
if "%Second:~0,1%" EQU "0" ( if "%Second:~1%" NEQ "" set "Second=%Second:~1%" )

rem Add 12 hours for time range 01:00:00 PM to 11:59:59 PM,
rem but keep the hour as is for 12:00:00 PM to 12:59:59 PM.
if "%Add12Hours%" == "1" (
    if %Hour% LSS 12 set /A Hour+=12
)
set "DateTime="
set "Add12Hours="

rem Must use 2 arrays as more than 31 tokens are not supported
rem by command line interpreter cmd.exe respectively command FOR.
set /A "Index1=Year-1979"
set /A "Index2=Index1-30"

if %Index1% LEQ 30 (
    rem Get number of days to year for the years 1980 to 2009.
    for /F "tokens=%Index1% delims= " %%Y in ("3652 4018 4383 4748 5113 5479 5844 6209 6574 6940 7305 7670 8035 8401 8766 9131 9496 9862 10227 10592 10957 11323 11688 12053 12418 12784 13149 13514 13879 14245") do set "Days=%%Y"
    for /F "tokens=%Index1% delims= " %%L in ("Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N") do set "LeapYear=%%L"
) else (
    rem Get number of days to year for the years 2010 to 2038.
    for /F "tokens=%Index2% delims= " %%Y in ("14610 14975 15340 15706 16071 16436 16801 17167 17532 17897 18262 18628 18993 19358 19723 20089 20454 20819 21184 21550 21915 22280 22645 23011 23376 23741 24106 24472 24837") do set "Days=%%Y"
    for /F "tokens=%Index2% delims= " %%L in ("N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N") do set "LeapYear=%%L"
)

rem Add the days to month in year.
if "%LeapYear%" == "N" (
    for /F "tokens=%Month% delims= " %%M in ("0 31 59 90 120 151 181 212 243 273 304 334") do set /A "Days+=%%M"
) else (
    for /F "tokens=%Month% delims= " %%M in ("0 31 60 91 121 152 182 213 244 274 305 335") do set /A "Days+=%%M"
)

rem Add the complete days in month of year.
set /A "Days+=Day-1"

rem Calculate the seconds which is easy now.
set /A "Seconds=Days*86400+Hour*3600+Minute*60+Second"

rem Exit this subroutine
goto :EOF

最適なパフォーマンスを得るには、すべてのコメントを削除することをお勧めします。つまり、0〜4の先行スペースの後のremで始まるすべての行を削除します。

また、配列を小さくすることもできます。つまり、上記のバッチコードで現在サポートされているように、時間範囲を1980-01-01 00:00:00から2038-01-19 03:14:07に減らし、たとえば2015-01にします。以下のコードでは-01から2019-12-31を使用しているため、C:\Tempフォルダーツリーで7日より古いファイルを実際に削除します。

さらに、以下のバッチコードは24時間形式に最適化されています。

@echo off
setlocal EnableDelayedExpansion
call :GetSeconds "%DATE:~-10% %TIME%"
set /A "LastWeek=Seconds-7*86400"

for /F "delims=" %%F in ('dir /A-D-H-S /B /S "C:\Temp"') do (
    call :GetSeconds "%%~tF:0"
    if !Seconds! LSS %LastWeek% del /F "%%~fF"
)
endlocal
goto :EOF

:GetSeconds
for /F "tokens=1-6 delims=,-./: " %%A in ("%~1") do (
    set "Day=%%B" & set "Month=%%A" & set "Year=%%C"
    set "Hour=%%D" & set "Minute=%%E" & set "Second=%%F"
)
if "%Month:~0,1%"  EQU "0" ( if "%Month:~1%"  NEQ "" set "Month=%Month:~1%"   )
if "%Day:~0,1%"    EQU "0" ( if "%Day:~1%"    NEQ "" set "Day=%Day:~1%"       )
if "%Hour:~0,1%"   EQU "0" ( if "%Hour:~1%"   NEQ "" set "Hour=%Hour:~1%"     )
if "%Minute:~0,1%" EQU "0" ( if "%Minute:~1%" NEQ "" set "Minute=%Minute:~1%" )
if "%Second:~0,1%" EQU "0" ( if "%Second:~1%" NEQ "" set "Second=%Second:~1%" )
set /A "Index=Year-2014"
for /F "tokens=%Index% delims= " %%Y in ("16436 16801 17167 17532 17897") do set "Days=%%Y"
for /F "tokens=%Index% delims= " %%L in ("N Y N N N") do set "LeapYear=%%L"
if "%LeapYear%" == "N" (
    for /F "tokens=%Month% delims= " %%M in ("0 31 59 90 120 151 181 212 243 273 304 334") do set /A "Days+=%%M"
) else (
    for /F "tokens=%Month% delims= " %%M in ("0 31 60 91 121 152 182 213 244 274 305 335") do set /A "Days+=%%M"
)
set /A "Days+=Day-1"
set /A "Seconds=Days*86400+Hour*3600+Minute*60+Second"
goto :EOF

Windowsでの日付と時刻の形式とファイル時間の比較の詳細については、ファイルの時間に関する多くの追加情報を含むバッチファイルファイルが4時間より古いかどうかを確認するに関する私の回答を参照してください。


9

このコードをコピーして、として保存しますDelOldFiles.vbs

CMDでの使用: cscript //nologo DelOldFiles.vbs 15

15は、過去15日より古いファイルを削除することを意味します。

  'copy from here
    Function DeleteOlderFiles(whichfolder)
       Dim fso, f, f1, fc, n, ThresholdDate
       Set fso = CreateObject("Scripting.FileSystemObject")
       Set f = fso.GetFolder(whichfolder)
       Set fc = f.Files
       Set objArgs = WScript.Arguments
       n = 0
       If objArgs.Count=0 Then
           howmuchdaysinpast = 0
       Else
           howmuchdaysinpast = -objArgs(0)
       End If
       ThresholdDate = DateAdd("d", howmuchdaysinpast, Date)   
       For Each f1 in fc
     If f1.DateLastModified<ThresholdDate Then
        Wscript.StdOut.WriteLine f1
        f1.Delete
        n = n + 1    
     End If
       Next
       Wscript.StdOut.WriteLine "Deleted " & n & " file(s)."
    End Function

    If Not WScript.FullName = WScript.Path & "\cscript.exe" Then
      WScript.Echo "USAGE ONLY IN COMMAND PROMPT: cscript DelOldFiles.vbs 15" & vbCrLf & "15 means to delete files older than 15 days in past."
      WScript.Quit 0   
    End If

    DeleteOlderFiles(".")
 'to here

8

Windows Server 2008 R2の場合:

forfiles /P c:\sql_backups\ /S /M *.sql /D -90 /C "cmd /c del @PATH"

これにより、90日以上経過したすべての.sqlファイルが削除されます。


7

forfilesを使用します。

異なるバージョンがあります。初期のものはUNIXスタイルのパラメーターを使用します。

私のバージョン(サーバー2000の場合-スイッチの後にスペースがないことに注意してください)-

forfiles -p"C:\what\ever" -s -m*.* -d<number of days> -c"cmd /c del @path"

XPにforfilesを追加するには、からexeファイルを取得するftp://ftp.microsoft.com/ResKit/y2kfix/x86/

そしてそれをC:\ WINDOWS \ system32に追加します


11
@Kibbeeそれは同じ答えではなく、構文が異なります。これは、助けようとする巧妙な試みでした。Windowsのコマンドラインをほとんど知らないので、これを機能させるために何時間も苛立たせました。私にとって重要な情報は、バージョンが異なる(構文が異なる)こと、スペースを削除する必要があることです。これらのどちらも元の回答には含まれていませんでした。(私は答えについてコメントしたでしょうが、私には特権がありません
Aidan Ewen

他の回答と同じエラー(承認されたものを含む)。ワイルドカード入力*.*すべてのファイルとforfiles一致しません。名前が一致するファイル(拡張子のあるファイル)のみを照合します。OPは、ファイル名に要求することについて何も述べていません。適切なパラメータはですが、これがデフォルトです。まったく必要はありません。../M */M
AnT、2018年

7

Windows 2012 R2の場合、以下が機能します。

    forfiles /p "c:\FOLDERpath" /d -30 /c "cmd /c del @path"

削除されるファイルを確認するには、これを使用します

    forfiles /p "c:\FOLDERpath" /d -30 /c "cmd /c echo @path @fdate"

Windows Server 2008の中から7以上およびWindowsこれさえ作品
kwrl

6

IMO、JavaScriptは徐々に一般的なスクリプト標準になりつつあります。おそらく他のスクリプト言語よりも多くの製品で利用可能です(Windowsでは、Windows Scripting Hostを使用して利用できます)。たくさんのフォルダにある古いファイルを削除する必要があるので、次のJavaScript関数を実行します。

// run from an administrator command prompt (or from task scheduler with full rights):  wscript jscript.js
// debug with:   wscript /d /x jscript.js

var fs = WScript.CreateObject("Scripting.FileSystemObject");

clearFolder('C:\\temp\\cleanup');

function clearFolder(folderPath)
{
    // calculate date 3 days ago
    var dateNow = new Date();
    var dateTest = new Date();
    dateTest.setDate(dateNow.getDate() - 3);

    var folder = fs.GetFolder(folderPath);
    var files = folder.Files;

    for( var it = new Enumerator(files); !it.atEnd(); it.moveNext() )
    {
        var file = it.item();

        if( file.DateLastModified < dateTest)
        {
            var filename = file.name;
            var ext = filename.split('.').pop().toLowerCase();

            if (ext != 'exe' && ext != 'dll')
            {
                file.Delete(true);
            }
        }
    }

    var subfolders = new Enumerator(folder.SubFolders);
    for (; !subfolders.atEnd(); subfolders.moveNext())
    {
        clearFolder(subfolders.item().Path);
    }
}

クリアするフォルダーごとに、clearFolder()関数への別の呼び出しを追加するだけです。この特定のコードは、exeファイルとdllファイルも保持し、サブフォルダーもクリーンアップします。


6

うるう年を考慮に入れるための7daysclean.cmdのこの変更はどうですか?

10行未満のコーディングで実行できます。

set /a Leap=0
if (Month GEQ 2 and ((Years%4 EQL 0 and Years%100 NEQ 0) or Years%400 EQL 0)) set /a Leap=day
set /a Months=!_months!+Leap

Mofiによる編集:

上記の条件は、JRによって提供され、常にfalseと評価されます。、無効な構文のため、とます。

またMonth GEQ 2、うるう年には、3月から12月までの月にのみ86400秒を追加する必要がありますが、2月は必要ありません。

うるう日を考慮に入れる作業コード-現在の年のみ- ジェイによって投稿されたバッチファイル7daysclean.cmdで:

set "LeapDaySecs=0"
if %Month% LEQ 2 goto CalcMonths
set /a "LeapRule=Years%%4"
if %LeapRule% NEQ 0 goto CalcMonths
rem The other 2 rules can be ignored up to year 2100.
set /A "LeapDaySecs=day"
:CalcMonths
set /a Months=!_months!+LeapDaySecs

5

この貴重なスレッドにささやかな貢献を加えるかもしれません。他のソリューションが実際のエラーテキストを取り除く可能性があることを発見しましたが、アプリケーションの失敗を示す%ERRORLEVEL%を無視しています。また、「ファイルが見つかりません」エラーでない限り、%ERRORLEVEL%を合法的に使用します。

いくつかの例:

具体的にエラーをデバッグして排除する:

forfiles /p "[file path...]\IDOC_ARCHIVE" /s /m *.txt /d -1 /c "cmd /c del @path" 2>&1 |  findstr /V /O /C:"ERROR: No files found with the specified search criteria."2>&1 | findstr ERROR&&ECHO found error||echo found success

ワンライナーを使用してERRORLEVELの成功または失敗を返す:

forfiles /p "[file path...]\IDOC_ARCHIVE" /s /m *.txt /d -1 /c "cmd /c del @path" 2>&1 |  findstr /V /O /C:"ERROR: No files found with the specified search criteria."2>&1 | findstr ERROR&&EXIT /B 1||EXIT /B 0

ワンライナーを使用して、他のコードの最中にあるバッチファイルのコンテキスト内で成功するためにERRORLEVELをゼロに維持します(ver> nulはERRORLEVELをリセットします)。

forfiles /p "[file path...]\IDOC_ARCHIVE" /s /m *.txt /d -1 /c "cmd /c del @path" 2>&1 |  findstr /V /O /C:"ERROR: No files found with the specified search criteria."2>&1 | findstr ERROR&&ECHO found error||ver > nul

SQL ServerエージェントのCmdExecジョブステップの場合、私は次のことに着手しました。バグかどうかはわかりませんが、ステップ内のCmdExecはコードの最初の行しか認識しません。

cmd /e:on /c "forfiles /p "C:\SQLADMIN\MAINTREPORTS\SQL2" /s /m *.txt /d -1 /c "cmd /c del @path" 2>&1 |  findstr /V /O /C:"ERROR: No files found with the specified search criteria."2>&1 | findstr ERROR&&EXIT 1||EXIT 0"&exit %errorlevel%

5

おっと、すでにたくさんの答え。私が見つけたシンプルで便利なルートは、パラメーターを使用して、Windowsの単一のコマンドライン命令からROBOCOPY.EXEを2回連続して実行することでした。

ROBOCOPY.EXE SOURCE-DIR TARGET-DIR *.* /MOV /MINAGE:30 & ROBOCOPY.EXE SOURCE-DIR TARGET-DIR *.* /MOV /MINAGE:30 /PURGE

この例では、30日以上経過したすべてのファイル()を選択し、それらをターゲットフォルダーに移動することで機能します。2番目のコマンドは、PURGEコマンドを追加して同じことをもう一度行います。これは、ソースフォルダーに存在しないターゲットフォルダー内のファイルを削除することを意味します。つまり、基本的に、最初のコマンドはファイルを移動し、2番目のコマンドは、2番目のコマンドが呼び出されたときにソースフォルダーに存在しないため、DELETESを実行します。

ROBOCOPYのドキュメントを参照し、テスト時には/ Lスイッチを使用してください。


4

XPリソースキットがある場合、robocopyを使用してすべての古いディレクトリを単一のディレクトリに移動し、rmdirを使用してそのディレクトリのみを削除できます。

mkdir c:\temp\OldDirectoriesGoHere
robocopy c:\logs\SoManyDirectoriesToDelete\ c:\temp\OldDirectoriesGoHere\ /move /minage:7
rmdir /s /q c:\temp\OldDirectoriesGoHere

4

e.Jamesの回答は、変更されていないバージョンのWindowsでもWindows 2000 SP4(および場合によってはそれ以前)で機能するので良いと思いますが、外部ファイルへの書き込みが必要でした。以下は、互換性を維持しながら外部テキストファイルを作成しない修正バージョンです。

REM del_old.cmd
REM usage: del_old MM-DD-YYYY
setlocal enabledelayedexpansion
for /f "tokens=*" %%a IN ('xcopy *.* /d:%1 /L /I null') do @if exist "%%~nxa" set "excludefiles=!excludefiles!;;%%~nxa;;"
for /f "tokens=*" %%a IN ('dir /b') do @(@echo "%excludefiles%"|FINDSTR /C:";;%%a;;">nul || if exist "%%~nxa" DEL /F /Q "%%a">nul 2>&1)

元の質問に忠実にするために、ここでは、日数をパラメーターとして呼び出した場合に、すべての計算を実行するスクリプトを示します。

REM del_old_compute.cmd
REM usage: del_old_compute N
setlocal enabledelayedexpansion
set /a days=%1&set cur_y=%DATE:~10,4%&set cur_m=%DATE:~4,2%&set cur_d=%DATE:~7,2%
for /f "tokens=1 delims==" %%a in ('set cur_') do if "!%%a:~0,1!"=="0" set /a %%a=!%%a:~1,1!+0
set mo_2=28&set /a leapyear=cur_y*10/4
if %leapyear:~-1% equ 0 set mo_2=29
set mo_1=31&set mo_3=31&set mo_4=30&set mo_5=31
set mo_6=30&set mo_7=31&set mo_8=31&set mo_9=30
set mo_10=31&set mo_11=30&set mo_12=31
set /a past_y=(days/365)
set /a monthdays=days-((past_y*365)+((past_y/4)*1))&&set /a past_y=cur_y-past_y&set months=0
:setmonth
set /a minusmonth=(cur_m-1)-months
if %minusmonth% leq 0 set /a minusmonth+=12
set /a checkdays=(mo_%minusmonth%)
if %monthdays% geq %checkdays% set /a months+=1&set /a monthdays-=checkdays&goto :setmonth
set /a past_m=cur_m-months
set /a lastmonth=cur_m-1
if %lastmonth% leq 0 set /a lastmonth+=12
set /a lastmonth=mo_%lastmonth%
set /a past_d=cur_d-monthdays&set adddays=::
if %past_d% leq 0 (set /a past_m-=1&set adddays=)
if %past_m% leq 0 (set /a past_m+=12&set /a past_y-=1)
set mo_2=28&set /a leapyear=past_y*10/4
if %leapyear:~-1% equ 0 set mo_2=29
%adddays%set /a past_d+=mo_%past_m%
set d=%past_m%-%past_d%-%past_y%
for /f "tokens=*" %%a IN ('xcopy *.* /d:%d% /L /I null') do @if exist "%%~nxa" set "excludefiles=!excludefiles!;;%%~nxa;;"
for /f "tokens=*" %%a IN ('dir /b') do @(@echo "%excludefiles%"|FINDSTR /C:";;%%a;;">nul || if exist "%%~nxa" DEL /F /Q "%%a">nul 2>&1)

注:上記のコードは、うるう年と各月の正確な日数を考慮に入れています。唯一の最大値は、0/0/0から経過した日数の合計です(その後、負の年を返します)。

注:数学は一方向にしか進みません。負の入力から将来の日付を正しく取得できません(試行はしますが、月の最終日を過ぎる可能性があります)。


3

あなたはこれをやってのけることができるかもしれません。あなたはを見てとることができ、この質問に簡単たとえば、。日付の比較を開始すると、複雑になります。日付が大きいかどうかは簡単にわかりますが、2つの日付の差を実際に取得する必要があるかどうかを検討する必要がある状況は多数あります。

つまり、サードパーティのツールを実際に使用できない場合を除いて、これを発明しようとしないでください。


3

これは驚くべきことではありませんが、今日はこのようなことをしてスケジュールされたタスクなどとして実行する必要がありました。

バッチファイル、DelFilesOlderThanNDays.batとサンプルexec w / params:

DelFilesOlderThanNDays.bat 7 C:\ dir1 \ dir2 \ dir3 \ logs * .log

echo off
cls
Echo(
SET keepDD=%1
SET logPath=%2 :: example C:\dir1\dir2\dir3\logs
SET logFileExt=%3
SET check=0
IF [%3] EQU [] SET logFileExt=*.log & echo: file extention not specified (default set to "*.log")
IF [%2] EQU [] echo: file directory no specified (a required parameter), exiting! & EXIT /B 
IF [%1] EQU [] echo: number of days not specified? :)
echo(
echo: in path [ %logPath% ]
echo: finding all files like [ %logFileExt% ]
echo: older than [ %keepDD% ] days
echo(
::
::
:: LOG
echo:  >> c:\trimLogFiles\logBat\log.txt
echo: executed on %DATE% %TIME% >> c:\trimLogFiles\logBat\log.txt
echo: ---------------------------------------------------------- >> c:\trimLogFiles\logBat\log.txt
echo: in path [ %logPath% ] >> c:\trimLogFiles\logBat\log.txt
echo: finding all files like [ %logFileExt% ] >> c:\trimLogFiles\logBat\log.txt
echo: older than [ %keepDD% ] days >> c:\trimLogFiles\logBat\log.txt
echo: ---------------------------------------------------------- >> c:\trimLogFiles\logBat\log.txt
::
FORFILES /p %logPath% /s /m %logFileExt% /d -%keepDD% /c "cmd /c echo @path" >> c:\trimLogFiles\logBat\log.txt 2<&1
IF %ERRORLEVEL% EQU 0 (
 FORFILES /p %logPath% /s /m %logFileExt% /d -%keepDD% /c "cmd /c echo @path"
)
::
::
:: LOG
IF %ERRORLEVEL% EQU 0 (
 echo:  >> c:\trimLogFiles\logBat\log.txt
 echo: deleting files ... >> c:\trimLogFiles\logBat\log.txt
 echo:  >> c:\trimLogFiles\logBat\log.txt
 SET check=1
)
::
::
IF %check% EQU 1 (
 FORFILES /p %logPath% /s /m %logFileExt% /d -%keepDD% /c "cmd /c del @path"
)
::
:: RETURN & LOG
::
IF %ERRORLEVEL% EQU 0 echo: deletion successfull! & echo: deletion successfull! >> c:\trimLogFiles\logBat\log.txt
echo: ---------------------------------------------------------- >> c:\trimLogFiles\logBat\log.txt

3

akuの答えを拡張すると、UNCパスについて質問する人がたくさんいます。uncパスをドライブ文字にマッピングするだけで、forfileが幸せになります。ドライブのマッピングとマッピング解除は、たとえばバッチファイルでプログラムによって実行できます。

net use Z: /delete
net use Z: \\unc\path\to\my\folder
forfiles /p Z: /s /m *.gz /D -7 /C "cmd /c del @path"

これにより、7日より古い.gz拡張子を持つすべてのファイルが削除されます。使用する前にZ:が他にマッピングされていないことを確認したい場合は、次のように簡単なことを実行できます。

net use Z: \\unc\path\to\my\folder
if %errorlevel% equ 0 (
    forfiles /p Z: /s /m *.gz /D -7 /C "cmd /c del @path"
) else (
    echo "Z: is already in use, please use another drive letter!"
)

3

ROBOCOPYは私にとって素晴らしい働きをします。もともと私のイマンを提案した。ただし、ファイル/フォルダーを一時ディレクトリに移動してから一時フォルダーの内容を削除する代わりに、ファイルをゴミ箱に移動します!!!

これは、たとえば、次のバックアップバッチファイルの数行です。

SET FilesToClean1=C:\Users\pauls12\Temp
SET FilesToClean2=C:\Users\pauls12\Desktop\1616 - Champlain\Engineering\CAD\Backups

SET RecycleBin=C:\$Recycle.Bin\S-1-5-21-1480896384-1411656790-2242726676-748474

robocopy "%FilesToClean1%" "%RecycleBin%" /mov /MINLAD:15 /XA:SH /NC /NDL /NJH /NS /NP /NJS
robocopy "%FilesToClean2%" "%RecycleBin%" /mov /MINLAD:30 /XA:SH /NC /NDL /NJH /NS /NP /NJS

「Temp」フォルダーから15日以上古いものはすべて削除され、AutoCADバックアップフォルダー内のすべてのものは30日後に削除されます。変数を使用しているのは、ラインが非常に長くなり、他の場所で再利用できるためです。ログインに関連付けられたごみ箱へのdosパスを見つけるだけです。

これは私にとっては仕事用のコンピューター上にあり、機能します。より制限された権利をお持ちの方もいらっしゃると思いますが、とにかく試してみてください;)ROBOCOPYパラメータの説明については、Googleを検索してください。

乾杯!


1
既存の2番目に支持されている回答もRoboCopyを支持しています。もちろん、使用するオプションは多少異なりますが、既存の回答に近いものです。
ジョナサンレフラー

2
この投稿には新しいコンテンツがあります-ファイルをごみ箱に移動しています。これはRobocopyではまだ提案されておらず、組み込みの単一行コマンドを使用して元の投稿に完全に回答します。ファイルはごみ箱から復元できるため、「DEL」コマンドと「RMDIR」コマンドを組み合わせるよりも機能します。こんにちは、私はまだ新しいです-休憩してください;)
Shawn Pauliszyn

2

特定の年より古いファイルを削除するスクリプト:

@REM _______ GENERATE A CMD TO DELETE FILES OLDER THAN A GIVEN YEAR
@REM _______ (given in _olderthanyear variable)
@REM _______ (you must LOCALIZE the script depending on the dir cmd console output)
@REM _______ (we assume here the following line's format "11/06/2017  15:04            58 389 SpeechToText.zip")

@set _targetdir=c:\temp
@set _olderthanyear=2017

@set _outfile1="%temp%\deleteoldfiles.1.tmp.txt"
@set _outfile2="%temp%\deleteoldfiles.2.tmp.txt"

  @if not exist "%_targetdir%" (call :process_error 1 DIR_NOT_FOUND "%_targetdir%") & (goto :end)

:main
  @dir /a-d-h-s /s /b %_targetdir%\*>%_outfile1%
  @for /F "tokens=*" %%F in ('type %_outfile1%') do @call :process_file_path "%%F" %_outfile2%
  @goto :end

:end
  @rem ___ cleanup and exit
  @if exist %_outfile1% del %_outfile1%
  @if exist %_outfile2% del %_outfile2%
  @goto :eof

:process_file_path %1 %2
  @rem ___ get date info of the %1 file path
  @dir %1 | find "/" | find ":" > %2
  @for /F "tokens=*" %%L in ('type %2') do @call :process_line "%%L" %1
  @goto :eof

:process_line %1 %2
  @rem ___ generate a del command for each file older than %_olderthanyear%
  @set _var=%1
  @rem  LOCALIZE HERE (char-offset,string-length)
  @set _fileyear=%_var:~0,4%
  @set _fileyear=%_var:~7,4%
  @set _filepath=%2
  @if %_fileyear% LSS %_olderthanyear% echo @REM %_fileyear%
  @if %_fileyear% LSS %_olderthanyear% echo @del %_filepath%
  @goto :eof

:process_error %1 %2
  @echo RC=%1 MSG=%2 %3
  @goto :eof

1

これは私のためにやった。それは日付で動作し、あなたは過去の年に必要な量を差し引くことができます:

@echo off

set m=%date:~-7,2%
set /A m
set dateYear=%date:~-4,4%
set /A dateYear -= 2
set DATE_DIR=%date:~-10,2%.%m%.%dateYear% 

forfiles /p "C:\your\path\here\" /s /m *.* /d -%DATE_DIR% /c "cmd /c del @path /F"

pause

/Fcmd /c del @path /F力特定のファイルは、ファイルが読み取り専用にすることができ、場合によっては削除します。

これdateYearは年変数であり、そこでサブストラクションを自分のニーズに変更できます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.