Frage

Ich suche nach einer Möglichkeit, in einer Batchdatei alle Dateien zu löschen, die älter als 7 Tage sind.Ich habe im Internet gesucht und einige Beispiele mit Hunderten von Codezeilen gefunden, und andere, die die Installation zusätzlicher Befehlszeilen-Dienstprogramme erforderten, um die Aufgabe zu erfüllen.

Ähnliches kann sein gemacht in BASH in nur ein paar Codezeilen.Es scheint, dass für Batchdateien in Windows etwas zumindest einigermaßen Einfaches getan werden könnte.Ich suche nach einer Lösung, die in einer Standard-Windows-Eingabeaufforderung ohne zusätzliche Dienstprogramme funktioniert.Bitte auch kein PowerShell oder Cygwin.

War es hilfreich?

Lösung

Genießen:

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

Sehen forfile-Dokumentation für mehr Details.

Weitere Extras finden Sie unter Ein A-Z-Index der Windows XP-Befehlszeile.

Wenn nicht forfiles auf Ihrem Computer installiert ist, kopieren Sie es von einem beliebigen Windows Server 2003 auf Ihren Windows XP-Computer unter %WinDir%\system32\.Dies ist möglich, da die EXE-Datei vollständig kompatibel zwischen Windows Server 2003 und Windows XP ist.

In späteren Versionen von Windows und Windows Server ist es standardmäßig installiert.

Für Windows 7 und neuer (einschließlich Windows 10):

Die Syntax hat sich ein wenig geändert.Daher lautet der aktualisierte Befehl:

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

Andere Tipps

Führen Sie Folgendes aus Befehle:

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

Verschieben Sie alle Dateien (mit /mov, das Dateien verschiebt und dann löscht, im Gegensatz zu /move, das ganze Dateibäume verschiebt, die dann gelöscht werden) per Robocopy an einen anderen Speicherort und führen Sie dann einen Löschbefehl auf diesem Pfad aus, und schon sind Sie fertig Gut.

Auch wenn Sie ein Verzeichnis mit vielen Daten haben, können Sie es verwenden /mir schalten

Ok, ich war etwas gelangweilt und habe mir Folgendes ausgedacht, das meine Version eines für den täglichen Gebrauch begrenzten Linux-Epochenersatzes eines armen Mannes enthält (keine Zeiterhaltung):

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

VERWENDUNG

set /a strip=day*7 :Ändern 7 für die Anzahl der aufzubewahrenden Tage.

set dSource=C:\temp :Dies ist das Startverzeichnis für die Suche nach Dateien.

ANMERKUNGEN

Dies ist ein zerstörungsfreier Code, der anzeigt, was passiert wäre.

Ändern :

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

zu so etwas wie:

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

Dateien werden also tatsächlich gelöscht

Februar:ist fest auf 28 Tage codiert.Bissextiljahre sind wirklich eine Hölle, das hinzuzufügen.Wenn jemand eine Idee hat, die nicht das Hinzufügen von 10 Codezeilen erfordert, posten Sie sie, damit ich sie meinem Code hinzufüge.

Epoche:Ich habe die Zeit nicht berücksichtigt, da es darum geht, Dateien zu löschen, die älter als ein bestimmtes Datum sind. Wenn man Stunden/Minuten benötigt, wären Dateien von einem Tag gelöscht worden, der für die Aufbewahrung vorgesehen war.

EINSCHRÄNKUNG

Epoche geht davon aus, dass Ihr kurzes Datumsformat JJJJ-MM-TT ist.Es müsste für andere Einstellungen oder eine Laufzeitauswertung angepasst werden (sShortTime lesen, benutzergebundene Konfiguration, richtige Feldreihenfolge in einem Filter konfigurieren und den Filter verwenden, um die richtigen Daten aus dem Argument zu extrahieren).

Habe ich erwähnt, dass ich die automatische Formatierung dieses Editors hasse?Es entfernt die Leerzeilen und das Kopieren und Einfügen ist eine Hölle.

Ich hoffe das hilft.

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

Du solltest tun /d -3 (3 Tage früher) Das funktioniert gut für mich.Alle komplizierten Chargen könnten also im Mülleimer landen.Auch forfiles unterstützen keine UNC-Pfade. Stellen Sie daher eine Netzwerkverbindung zu einem bestimmten Laufwerk her.

Schauen Sie sich meine an Antwort zu einem ähnliche Frage:

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"

Dadurch werden Dateien gelöscht, die älter als ein bestimmtes Datum sind.Ich bin sicher, dass es geändert werden kann, um sieben Tage vom aktuellen Datum an zurückzugehen.

aktualisieren: Mir ist aufgefallen, dass HerbCSO das obige Skript verbessert hat.Ich empfehle die Verwendung seine Version stattdessen.

Mein Befehl ist

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

@PATH - ist in meinem Fall nur ein Pfad, also musste ich ihn verwenden @PATH\@FILE

Auch forfiles /? Funktioniert bei mir auch nicht, aber forfiles (ohne „?“) hat gut funktioniert.

Und die einzige Frage, die ich habe:So fügen Sie mehrere Masken hinzu (zum Beispiel „.log|.bak")?

All dies bezüglich forfiles.exe, das ich hier heruntergeladen (auf Win XP)

Wenn Sie jedoch einen Windows-Server verwenden, sollte forfiles.exe bereits vorhanden sein und unterscheidet sich von der FTP-Version.Deshalb sollte ich den Befehl ändern.

Für Windows Server 2003 verwende ich diesen Befehl:

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

Für Windows Server 2008 R2:

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

Dadurch werden alle gelöscht .sql Dateien älter als 90 Tage.

Kopieren Sie diesen Code und speichern Sie ihn als DelOldFiles.vbs.

NUR IN DER EINGABEEINGABE VERWENDEN:cscript DelOldFiles.vbs 15

15 bedeutet, dass Dateien gelöscht werden, die älter als 15 Tage sind.

  '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

Verwenden Sie forfiles.

Es gibt verschiedene Versionen.Die ersten verwendeten Parameter im Unix-Stil.

Meine Version (für Server 2000 – beachten Sie, dass nach den Schaltern kein Leerzeichen steht) –

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

Um forfiles zu XP hinzuzufügen, holen Sie sich die Exe-Datei von ftp://ftp.microsoft.com/ResKit/y2kfix/x86/

und fügen Sie es zu C:\WINDOWS\system32 hinzu

Für Windows 2012 R2 würde Folgendes funktionieren:

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

Um die Dateien anzuzeigen, die gelöscht werden, verwenden Sie diese Option

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

Meiner Meinung nach entwickelt sich JavaScript allmählich zu einem universellen Skriptstandard:Sie ist wahrscheinlich in mehr Produkten verfügbar als jede andere Skriptsprache (in Windows ist sie über den Windows Scripting Host verfügbar).Ich muss alte Dateien in vielen Ordnern bereinigen, daher ist hier eine JavaScript-Funktion, die das erledigt:

// 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);
    }
}

Fügen Sie für jeden zu löschenden Ordner einfach einen weiteren Aufruf der Funktion „clearFolder()“ hinzu.Dieser spezielle Code behält auch Exe- und DLL-Dateien bei und bereinigt auch Unterordner.

Wie wäre es mit dieser Änderung? 7daysclean.cmd ein Schaltjahr berücksichtigen?

Es kann in weniger als 10 Zeilen Codierung durchgeführt werden!

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

Bearbeiten von Mofi:

Die obige Bedingung trug bei J.R. wertet immer aus FALSCH wegen ungültiger Syntax.

Und Month GEQ 2 ist auch deshalb falsch, weil das Hinzufügen von 86400 Sekunden für einen weiteren Tag in einem Schaltjahr nur für die Monate März bis Dezember erfolgen muss, nicht jedoch für Februar.

Ein Arbeitscode zur Berücksichtigung von Schalttagen – nur im aktuellen Jahr – in der Batchdatei 7daysclean.cmd Geschrieben von Jay wäre:

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

Es gibt sehr oft relative Datums-/Uhrzeit-bezogene Fragen, die mit einer Batch-Datei gelöst werden müssen.Aber Befehlszeileninterpreter cmd.exe hat keine Funktion für Datums-/Uhrzeitberechnungen.Viele gut funktionierende Lösungen, die zusätzliche Konsolenanwendungen oder Skripte verwenden, wurden bereits hier, auf anderen Seiten von Stack Overflow und auf anderen Websites veröffentlicht.

Bei Vorgängen, die auf Datum/Uhrzeit basieren, ist es üblich, eine Datums-/Uhrzeitzeichenfolge in Sekunden seit einem bestimmten Tag umzuwandeln.Sehr häufig ist 1970-01-01 00:00:00 UTC.Abhängig vom Datumsbereich, der zur Unterstützung einer bestimmten Aufgabe erforderlich ist, kann jedoch auch jeder spätere Tag verwendet werden.

Jay Gesendet 7daysclean.cmd Enthält eine schnelle „Datums-zu-Sekunden“-Lösung für den Befehlszeileninterpreter cmd.exe.Aber Schaltjahre werden nicht korrekt berücksichtigt. J.R. gepostet an hinzufügen Auf um den Schalttag im laufenden Jahr zu berücksichtigen, aber die anderen Schaltjahre seit dem Basisjahr zu ignorieren, d. h.seit 1970.

Ich verwende seit 20 Jahren statische Tabellen (Arrays), die einmal mit einer kleinen C-Funktion erstellt wurden, um in meinen in C/C++ geschriebenen Anwendungen schnell die Anzahl der Tage einschließlich der Schalttage vom 01.01.1970 in Datums-/Uhrzeitkonvertierungsfunktionen zu ermitteln.

Diese sehr schnelle Tabellenmethode kann auch im Batch-Code verwendet werden FÜR Befehl.Also habe ich beschlossen, die Batch-Subroutine zu programmieren GetSeconds Hiermit wird die Anzahl der Sekunden seit dem 01.01.1970 um 00:00:00 UTC für eine an diese Routine übergebene Datums-/Uhrzeitzeichenfolge berechnet.

Notiz: Schaltsekunden werden nicht berücksichtigt, da die Windows-Dateisysteme ebenfalls keine Schaltsekunden unterstützen.

Zunächst die Tabellen:

  1. Tage seit 1970-01-01 00:00:00 UTC für jedes Jahr, einschließlich Schalttage.

    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
    

    Die Berechnung der Sekunden für die Jahre 2039 bis 2106 mit Epochenbeginn am 01.01.1970 ist nur mit einer vorzeichenlosen 32-Bit-Variablen möglich, d. h.unsigned long (oder unsigned int) in C/C++.

    Aber cmd.exe Verwenden Sie für mathematische Ausdrücke eine vorzeichenbehaftete 32-Bit-Variable.Daher ist der Maximalwert 2147483647 (0x7FFFFFFF), also 2038-01-19 03:14:07.

  2. Schaltjahrinformationen (Nein/Ja) für die Jahre 1970 bis 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. Anzahl der Tage bis zum ersten Tag jedes Monats im aktuellen Jahr.

                       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
    

Mit diesen Tabellen lässt sich ein Datum seit dem 01.01.1970 ganz einfach in Sekunden umrechnen.

Aufmerksamkeit bitte!

Das Format der Datums- und Uhrzeitzeichenfolgen hängt von den Windows-Regions- und Spracheinstellungen ab.Die Trennzeichen und die Reihenfolge der den Umgebungsvariablen zugewiesenen Token Day, Month Und Year Als Erstes FÜR Schleife von GetSeconds muss ggf. an das lokale Datums-/Uhrzeitformat angepasst werden.

Es ist notwendig, die Datumszeichenfolge der Umgebungsvariablen anzupassen, wenn das Datumsformat in der Umgebungsvariablen vorliegt DATUM unterscheidet sich vom vom Befehl verwendeten Datumsformat FÜR An %%~tF.

Zum Beispiel wann %DATE% erweitert sich auf Sun 02/08/2015 während %%~tF erweitert sich auf 02/08/2015 07:38 PM Der folgende Code kann verwendet werden, indem Zeile 4 wie folgt geändert wird:

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

Dies führt dazu, dass nur zur Unterroutine übergegangen wird 02/08/2015 - die Datumszeichenfolge ohne die 3 Buchstaben der Wochentagsabkürzung und das trennende Leerzeichen.

Alternativ könnte Folgendes verwendet werden, um das aktuelle Datum im richtigen Format zu übergeben:

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

Jetzt werden die letzten 10 Zeichen der Datumszeichenfolge an die Funktion übergeben GetSeconds und daher spielt es keine Rolle, ob die Datumszeichenfolge der Umgebungsvariablen ist DATUM ist mit oder ohne Wochentag, solange Tag und Monat immer zweistellig in der erwarteten Reihenfolge sind, d. h.im Format dd/mm/yyyy oder dd.mm.yyyy.

Hier ist der Batch-Code mit erläuternden Kommentaren, der lediglich ausgibt, welche Datei gelöscht und welche Datei beibehalten werden soll C:\Temp Ordnerbaum, siehe Code von zuerst FÜR Schleife.

@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

Für eine optimale Leistung wäre es am besten, alle Kommentare zu entfernen, d. h.alle Zeilen beginnen mit rem nach 0-4 führenden Leerzeichen.

Und die Arrays können auch kleiner gemacht werden, d.h.Verringern des Zeitbereichs von 1980-01-01 00:00:00 bis 2038-01-19 03:14:07, wie derzeit durch den Batch-Code oben unterstützt, zum Beispiel auf 2015-01-01 bis 2019-12-31 als Der folgende Code verwendet, der tatsächlich Dateien löscht, die älter als 7 Tage sind C:\Temp Ordnerbaum.

Darüber hinaus ist der Batch-Code unten für das 24-Stunden-Zeitformat optimiert.

@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

Weitere Informationen zu Datums- und Zeitformaten und Dateizeitvergleichen unter Windows finden Sie in meiner Antwort auf Finden Sie heraus, ob die Datei in der Batchdatei älter als 4 Stunden ist mit vielen Zusatzinformationen zu Dateizeiten.

Darf ich einen bescheidenen Beitrag zu diesem bereits wertvollen Thread hinzufügen?Ich stelle fest, dass andere Lösungen möglicherweise den eigentlichen Fehlertext entfernen, aber den %ERRORLEVEL% ignorieren, der einen Fehler in meiner Anwendung anzeigt.UND ich möchte zu Recht %ERRORLEVEL%, solange es nicht der Fehler „Keine Dateien gefunden“ ist.

Einige Beispiele:

Den Fehler gezielt debuggen und beheben:

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

Verwenden eines Einzeilers, um den Erfolg oder Misserfolg von ERRORLEVEL zurückzugeben:

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

Verwenden eines Einzeilers, um den ERRORLEVEL für den Erfolg im Kontext einer Batchdatei inmitten von anderem Code auf Null zu halten (ver > nul setzt den ERRORLEVEL zurück):

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

Bei einem SQL Server Agent CmdExec-Auftragsschritt bin ich auf Folgendes gestoßen.Ich weiß nicht, ob es ein Fehler ist, aber der CmdExec innerhalb des Schritts erkennt nur die erste Codezeile:

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%

Wenn Sie über das XP-Ressourcenkit verfügen, können Sie mithilfe von Robocopy alle alten Verzeichnisse in ein einziges Verzeichnis verschieben und dann mit rmdir nur dieses Verzeichnis löschen:

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

Ich finde e.James' Antwort ist gut, da es mit unveränderten Windows-Versionen bereits ab Windows 2000 SP4 (und möglicherweise früher) funktioniert, aber das Schreiben in eine externe Datei erforderlich war.Hier ist eine modifizierte Version, die keine externe Textdatei erstellt und gleichzeitig die Kompatibilität beibehält:

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)

Um der ursprünglichen Frage treu zu bleiben, handelt es sich hier um ein Skript, das ALLE Berechnungen für Sie erledigt, wenn Sie es mit der Anzahl der Tage als Parameter aufrufen:

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)

NOTIZ:Der obige Code berücksichtigt Schaltjahre sowie die genaue Anzahl der Tage in jedem Monat.Das einzige Maximum ist die Gesamtzahl der Tage seit 0/0/0 (danach werden negative Jahre zurückgegeben).

NOTIZ:Die Rechnung geht nur in eine Richtung;Es kann zukünftige Daten nicht korrekt aus negativen Eingaben ermitteln (es wird es versuchen, wird aber wahrscheinlich über den letzten Tag des Monats hinausgehen).

Vielleicht schaffst du das.Sie können einen Blick darauf werfen diese Frage, für ein einfacheres Beispiel.Die Komplexität entsteht, wenn man anfängt, die Daten zu vergleichen.Es kann leicht sein, festzustellen, ob das Datum größer ist oder nicht, aber es gibt viele Situationen, die berücksichtigt werden müssen, wenn Sie tatsächlich die Differenz zwischen zwei Datumsangaben ermitteln müssen.

Mit anderen Worten: Versuchen Sie nicht, dies zu erfinden, es sei denn, Sie können die Tools von Drittanbietern wirklich nicht verwenden.

Das ist nichts Großartiges, aber ich musste heute so etwas tun und es als geplante Aufgabe usw. ausführen.

Batchdatei, DelFilesOlderThanNDays.bat unten mit Beispiel-Exec mit Parametern:

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

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

Wenn ich die Antwort von Akus vertiefe, sehe ich viele Leute, die nach UNC-Pfaden fragen.Durch einfaches Zuordnen des UNC-Pfads zu einem Laufwerksbuchstaben werden Forfiles zufrieden sein.Das Zuordnen und Aufheben der Zuordnung von Laufwerken kann beispielsweise programmgesteuert in einer Batchdatei erfolgen.

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"

Dadurch werden alle Dateien mit der Erweiterung .gz gelöscht, die älter als 7 Tage sind.Wenn Sie sicherstellen möchten, dass Z:nichts anderem zugeordnet ist, bevor Sie es verwenden, können Sie etwas Einfaches tun wie

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!"
)

Meine Güte, schon viele Antworten.Ein einfacher und bequemer Weg, den ich gefunden habe, bestand darin, ROBOCOPY.EXE zweimal nacheinander von einer einzigen Windows-Befehlszeilenanweisung aus mit dem auszuführen & Parameter.

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

In diesem Beispiel funktioniert es, indem alle Dateien ausgewählt werden (.), die älter als 30 Tage sind, und verschieben Sie sie in den Zielordner.Der zweite Befehl macht dasselbe noch einmal mit dem Zusatz SÄUBERN Befehl, der bedeutet, Dateien im Zielordner zu entfernen, die im Quellordner nicht vorhanden sind.Im Wesentlichen verschiebt der erste Befehl also Dateien und der zweite löscht sie, da sie beim Aufruf des zweiten Befehls nicht mehr im Quellordner vorhanden sind.

Konsultieren Sie die Dokumentation von ROBOCOPY und verwenden Sie beim Testen den Schalter /L.

ROBOKOPIE funktioniert bei mir super.Ursprünglich schlug mein Iman vor.Aber anstatt die Dateien/Ordner in ein temporäres Verzeichnis zu verschieben und dann den Inhalt des temporären Ordners zu löschen, Verschiebe die Dateien in den Papierkorb!!!

Dies sind zum Beispiel ein paar Zeilen meiner Backup-Batchdatei:

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

Es entfernt alles, was älter als 15 Tage ist, aus meinem „Temp“-Ordner und 30 Tage lang alles in meinem AutoCAD-Sicherungsordner.Ich verwende Variablen, weil die Zeile ziemlich lang werden kann und ich sie für andere Standorte wiederverwenden kann.Sie müssen lediglich den DOS-Pfad zu Ihrem Papierkorb finden, der mit Ihrem Login verknüpft ist.

Das ist bei mir auf einem Arbeitscomputer und es funktioniert.Ich verstehe, dass einige von Ihnen möglicherweise restriktivere Rechte haben, aber versuchen Sie es trotzdem;) Suchen Sie bei Google nach Erklärungen zu den ROBOCOPY-Parametern.

Prost!

Dieser hat es für mich getan.Es funktioniert mit einem Datum und Sie können den gewünschten Betrag in Jahren abziehen, um in die Vergangenheit zu gehen:

@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

Die /F im cmd /c del @path /F Erzwingt das Löschen der spezifischen Datei. In einigen Fällen kann die Datei schreibgeschützt sein.

Die dateYear ist die Jahresvariable und dort können Sie die Subtraktion nach Ihren eigenen Bedürfnissen ändern

Mein Skript zum Löschen von Dateien, die älter als ein bestimmtes Jahr sind:

@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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top