Batch-Datei zum Löschen von Dateien, die älter als N Tage sind
-
09-06-2019 - |
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.
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:
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.
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
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