Plik wsadowy do usuwania plików starszych niż N dni

Szukam sposobu na usunięcie wszystkich plików starszych niż 7 dni w pliku wsadowym. Przeszukałem Sieć i znalazłem kilka przykładów z setkami linii kodu, a także inne, które wymagały zainstalowania dodatkowych narzędzi wiersza poleceń, aby wykonać zadanie.

Podobne rzeczy można wykonać w BASH w zaledwie kilku linijkach kodu. Wydaje się, że coś co najmniej zdalnie łatwe można zrobić dla plików wsadowych w systemie Windows. Szukam rozwiązania, które będzie działać w standardzie Wiersz polecenia systemu Windows, bez dodatkowych narzędzi. Proszę nie PowerShell lub Cygwin albo.

Author: Stephan, 2008-09-09

24 answers

Enjoy:

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

Zobacz dla dokumentacji pliku aby uzyskać więcej szczegółów.

Aby uzyskać więcej gadżetów, zapoznaj się z Indeks A-Z wiersza poleceń systemu Windows XP.

Jeśli nie masz zainstalowanego forfiles na swoim komputerze, skopiuj go z dowolnego Windows Server 2003 na swój komputer z systemem Windows XP pod adresem %WinDir%\system32\. Jest to możliwe, ponieważ EXE jest w pełni kompatybilny między Windows Server 2003 i Windows XP.

Późniejsze wersje Windows i Windows Server mają to zainstalowany domyślnie.

Dla Windows 7:

Składnia trochę się zmieniła. Dlatego zaktualizowaną komendą jest:

forfiles /p "C:\what\ever" /s /m *.* /D -<number of days> /C "cmd /c del @path"
 957
Author: aku,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-22 15:27:53

Uruchom następujące polecenia :

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

Przenieś wszystkie pliki (za pomocą /mov, który przenosi pliki, a następnie usuwa je w przeciwieństwie do /move, który przenosi całe linie plików, które są następnie usuwane) za pomocą robocopy do innej lokalizacji, a następnie wykonaj polecenie delete na tej ścieżce i wszystko będzie dobrze.

Również jeśli masz katalog z dużą ilością danych w nim można użyć /mir switch

 69
Author: Iman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-30 03:24:01

Ok trochę się nudziłem i wymyśliłem to, co zawiera moją wersję linuksowego zamiennika epoki biednego człowieka ograniczonego do codziennego użytku (bez zatrzymywania czasu): {]}

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

Użycie

set /a strip=day*7 : Zmień 7 na liczbę dni do zachowania.

set dSource=C:\temp : jest to katalog startowy do sprawdzania plików.

Uwagi

To nieniszczący kod, wyświetli to, co by się stało.

Zmiana:

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

Do coś w stylu:

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

Więc pliki są usuwane

Luty : jest mocno zakodowany do 28 dni. Bissextile years to piekło do dodania, naprawdę. jeśli ktoś ma pomysł, który nie dodałby 10 linijek kodu, śmiało pisz, więc dodaję go do mojego kodu.

Epoch: nie brałem pod uwagę czasu, ponieważ potrzeba usunięcia plików starszych niż określona data, biorąc godziny / minuty usunęłyby pliki z dnia, który był przeznaczony dla trzymanie.

Ograniczenie

Epoch przyjmuje za pewnik krótki format daty To RRRR-MM-DD. Wymagałoby to dostosowania do innych ustawień lub oceny czasu wykonania (odczyt sShortTime, konfiguracja związana z użytkownikiem, skonfigurowanie odpowiedniej kolejności pól w filtrze i użycie filtra do wyodrębnienia poprawnych danych z argumentu).

Czy wspomniałem, że nienawidzę automatycznego formatowania tego edytora? usuwa puste linie i kopiuj-wklej to piekło.

Mam nadzieję, że to pomoże.
 21
Author: Jay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-15 17:08:23
forfiles /p "v:" /s /m *.* /d -3 /c "cmd /c del @path"
Powinieneś to zrobić (3 dni wcześniej). Więc wszystkie skomplikowane partie mogą być w koszu na śmieci. Ponadto forfiles nie obsługuje ścieżek UNC, więc nawiąż połączenie sieciowe z określonym dyskiem.
 17
Author: Arno Jansen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-01 08:05:20

Spójrz na moją Odpowiedź na podobne pytanie :

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"

Usuwa pliki starsze niż podana data. Jestem pewien, że można go zmodyfikować, aby cofnąć się o siedem dni od bieżącej daty.

Update: zauważyłem, że HerbCSO poprawiło się na powyższym skrypcie. Zalecam użycie jego wersji zamiast tego.

 16
Author: e.James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:09

Moje polecenie to

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

@PATH - to tylko ścieżka w moim przypadku, więc musiałem użyć @PATH\@FILE

Również forfiles /? nie działa dla mnie zbyt, ale forfiles (bez "?") działał dobrze.

I jedyne pytanie jakie mam: jak dodać kilka masek (na przykład " .log / .bak")?

Wszystko o forfilach.exe że ja ściągnąłem tutaj (na win XP)

Ale jeśli używasz Windows server forfiles.exe powinien już tam być i różni się od wersji ftp. Że dlatego powinienem zmodyfikować komendę.

Dla Windows Server 2003 używam polecenia:

forfiles -p "d:\Backup" -s -m *.log -d -15 -c "cmd /c del @PATH"
 11
Author: segero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-01 08:06:34

Dla Windows Server 2008 R2:

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

To usunie wszystkie .pliki SQL starsze niż 90 dni.

 7
Author: NotJustClarkKent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-27 22:41:04

Skopiuj ten kod i zapisz go jako DelOldFiles.vbs.

Użycie tylko w wierszu polecenia: cscript DelOldFiles.vbs 15

15 oznacza usuwanie plików starszych niż 15 dni w przeszłości.

  '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
 6
Author: Paris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-26 01:36:21

Użyj forfiles.

Istnieją różne wersje. Wczesne używają uniksowych parametrów stylu.

Moja wersja (dla serwera 2000-Uwaga brak miejsca po przełącznikach) -

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

Aby dodać forfiles do XP, Pobierz exe z ftp://ftp.microsoft.com/ResKit/y2kfix/x86/

I dodać do C:\WINDOWS\system32

 6
Author: Aidan Ewen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-14 15:14:50

IMO JavaScript stopniowo staje się uniwersalnym standardem skryptowym: prawdopodobnie jest dostępny w większej liczbie produktów niż jakikolwiek inny język skryptowy (w systemie Windows jest dostępny przy użyciu hosta skryptowego Windows). Muszę wyczyścić stare pliki w wielu folderach, więc tutaj jest funkcja JavaScript, aby to zrobić:

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

Aby każdy folder został wyczyszczony, wystarczy dodać kolejne wywołanie do funkcji clearFolder (). Ten konkretny kod zachowuje również pliki exe i dll oraz czyści podfoldery jako cóż.

 5
Author: Graham Laight,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-26 10:57:48

A co z tą modyfikacją na 7daysclean.cmd wziąć pod uwagę rok przestępny?

Można to zrobić w mniej niż 10 liniach kodowania!

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

Edit by Mofi:

Powyższy warunek dodany przez J. R. ocenia zawsze na false ze względu na nieprawidłową składnię.

I Month GEQ 2 jest również błędne, ponieważ dodanie 86400 sekund na jeden dzień więcej musi być wykonane w roku przestępnym tylko dla miesięcy od marca do grudnia, ale nie dla Luty.

Roboczy kod uwzględniający dzień przestępny-tylko w bieżącym roku-w pliku wsadowym 7daysclean.cmd wysłany przez Jay będzie:

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
Author: J.R.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:09

W systemie windows 2012 R2 będzie działać:

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

Aby zobaczyć pliki, które zostaną usunięte użyj tego

    forfiles /p "c:\FOLDERpath" /d -30 /c "cmd /c echo @path @fdate"
 5
Author: Viktor Ka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-25 15:37:04

Bardzo często można rozwiązać pytania związane z datą/czasem za pomocą pliku wsadowego. Ale interpreter linii poleceń cmd.exe nie ma funkcji do obliczania daty/czasu. Wiele dobrze działających rozwiązań wykorzystujących dodatkowe aplikacje konsolowe lub skrypty zostało już zamieszczonych tutaj, na innych stronach Stack Overflow i na innych stronach internetowych.

Powszechnym dla operacji opartych na dacie/czasie jest wymóg konwersji ciągu daty / czasu na sekundy od określonego dnia. Bardzo / 2010-01-01 00: 00: 00 Ale każdy późniejszy dzień może być również używany w zależności od zakresu dat wymaganego do obsługi określonego zadania.

Jay posted 7daysclean.cmd zawiera szybkie rozwiązanie "date to seconds" dla interpretera wiersza poleceń cmd.exe . Nie uwzględnia jednak lat przestępnych. J. R. opublikował dodatek za uwzględnienie dnia przestępnego w bieżącym roku, ale ignorowanie innych lat przestępnych od bazy roku, tj. od 1970 roku.

Używam od 20 lat statycznych tabel (tablic) utworzonych raz z małą funkcją C, aby szybko uzyskać liczbę dni wliczając w to dni przestępne od 1970-01-01 w funkcjach konwersji daty/czasu w moich aplikacjach napisanych w C / C++.

Ta bardzo szybka metoda tabelkowa może być również używana w kodzie wsadowym za pomocą dla polecenia. Postanowiłem więc zakodować podprogram wsadowy GetSeconds, który oblicza liczbę sekund od 1970-01-01 00: 00: 00 UTC Dla daty / czasu / align = "left" /

Uwaga: sekundy przestępne nie są brane pod uwagę, ponieważ systemy plików Windows również nie obsługują sekund przestępnych.

Najpierw tabele:

  1. Dni od 1970-01-01 00: 00: 00 UTC za każdy rok włącznie z dniami przestępnymi.

    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
    

    Obliczanie sekund dla roku 2039 do 2106 z epoką rozpoczynającą się od 1970-01-01 jest możliwe tylko przy użyciu unsigned 32-bitowej zmiennej, tj. unsigned long (lub unsigned int) w C / C++.

    Ale cmd.exe Użyj dla wyrażeń matematycznych podpisanej zmiennej 32-bitowej. Dlatego maksymalna wartość to 2147483647 (0x7FFFFFFF), czyli 2038-01-19 03:14:07.

  2. Informacje o roku przestępnym (nie/tak) dla lat 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. Liczba dni do pierwszego dnia każdego miesiąca w bieżącym roku.

                       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
    

Konwersja daty na liczbę sekund od 1970-01-01 jest dość łatwa przy użyciu tych stoły.

Proszę O uwagę!

Format łańcuchów daty i czasu zależy od ustawień regionu i języka systemu Windows. Ograniczniki i kolejność tokenów przypisanych do zmiennych środowiskowychDay, Month i Year w pierwszym dla pętla GetSeconds musi być dostosowana do lokalnego formatu daty/czasu, jeśli to konieczne.

Konieczne jest dostosowanie ciągu daty zmiennej środowiskowej, jeśli format daty w zmiennej środowiskowej Data jest inny niż format daty używany przez polecenie dla na %%~tF.

Na przykład gdy %DATE% rozszerza się do Sun 02/08/2015 podczas gdy %%~tF rozszerza się do 02/08/2015 07:38 PM poniższy kod może być użyty z modyfikacją linii 4 do:

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

Powoduje to przekazanie do podprogramu just 02/08/2015 - ciągu daty Bez 3 liter skrótu dnia tygodnia i oddzielającego znaku spacji.

Alternatywnie można użyć następującego wzoru, aby przekazać aktualną datę w prawidłowym formacie:

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

Teraz ostatnie 10 znaki z łańcucha daty są przekazywane do funkcji GetSeconds i dlatego nie ma znaczenia, czy łańcuch daty zmiennej środowiskowej DATE jest z lub bez dnia tygodnia, tak długo, jak dzień i miesiąc są zawsze z 2 cyframi w oczekiwanej kolejności, tzn. w formacie dd/mm/yyyy lub dd.mm.yyyy.

Oto kod wsadowy z komentarzem wyjaśniającym, który wyświetla, który plik należy usunąć, a który zachować w drzewie folderów C:\Temp, zobacz kod pierwszej pętli dla.

@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

Dla optymalnego wydajność najlepiej byłoby usunąć wszystkie komentarze, tzn. wszystkie linie zaczynające się od rem po spacjach 0-4.

I tablice mogą być również mniejsze, tzn. zmniejszając zakres czasowy od 1980-01-01 00:00:00 do 2038-01-19 03:14:07, jak obecnie wspierany przez powyższy kod wsadowy, na przykład do 2015-01-01 do 2019-12-31, jak używa poniższy kod, który naprawdę usuwa pliki starsze niż 7 dni w drzewie folderów C:\Temp.

Ponadto poniższy kod serii jest zoptymalizowany dla 24 godziny format czasu.

@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

Aby uzyskać jeszcze więcej informacji na temat formatów daty i czasu oraz porównań czasu plików w systemie Windows, zobacz moją odpowiedź na dowiedz się, czy plik jest starszy niż 4 godziny w pliku wsadowym z wieloma dodatkowymi informacjami na temat czasów plików.

 5
Author: Mofi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:54

Chciałbym dodać skromny wkład do tego i tak już cennego wątku. Znajduję, że inne rozwiązania mogą pozbyć się rzeczywistego tekstu błędu, ale ignorują % ERRORLEVEL%, który sygnalizuje awarię w mojej aplikacji. I zgodnie z prawem chcę %ERRORLEVEL% tak długo, jak nie jest to błąd "nie znaleziono plików".

Niektóre Przykłady:

Debugowanie i eliminowanie błędu w szczególności:

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

Korzystanie z oneliner, aby zwrócić sukces ERRORLEVEL lub awaria:

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

Używając onelinera, aby utrzymać poziom błędu na zero dla powodzenia w kontekście pliku batch pośród innego kodu (ver > nul resetuje poziom błędu):

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

Dla kroku zadania SQL Server Agent CmdExec wylądowałem na poniższym. Nie wiem czy to błąd, ale CmdExec w kroku rozpoznaje tylko pierwszą linię kodu:

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%
 4
Author: Sting,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-08 13:13:35

Jeśli masz XP resource kit, możesz użyć robocopy, aby przenieść wszystkie stare katalogi do jednego katalogu, a następnie użyć rmdir, aby usunąć tylko ten jeden:

mkdir c:\temp\OldDirectoriesGoHere
robocopy c:\logs\SoManyDirectoriesToDelete\ c:\temp\OldDirectoriesGoHere\ /move /minage:7
rmdir /s /q c:\temp\OldDirectoriesGoHere
 3
Author: neuracnu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-08 00:56:02

Myślę, że e. odpowiedź Jamesa jest dobra, ponieważ działa z niezmodyfikowanymi wersjami Windows już w Windows 2000 SP4 (i prawdopodobnie wcześniej), ale wymagało to zapisu do zewnętrznego pliku. Oto zmodyfikowana wersja, która nie tworzy zewnętrznego pliku tekstowego przy zachowaniu zgodności:

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)

Aby być wiernym oryginalnemu pytaniu, tutaj jest w skrypcie, który wykonuje wszystkie obliczenia za Ciebie, jeśli wywołasz je z liczbą dni jako parametrem:

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)

Uwaga: Powyższy kod uwzględnia lata przestępne, a także dokładną liczbę dni w każdym miesiącu. Jedynym maksimum jest całkowita liczba dni, które były od 0/0/0 (po tym zwraca ujemne lata).

Uwaga: matematyka idzie tylko w jedną stronę; nie może poprawnie odczytać przyszłych dat z ujemnego wejścia (spróbuje, ale prawdopodobnie przejdzie do ostatniego dnia miesiąca).

 3
Author: Lectrode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:59

Być może uda ci się to zrobić. Możesz spojrzeć na to pytanie, aby uzyskać prostszy przykład. Złożoność przychodzi, kiedy zaczynasz porównywać daty. Może być łatwo powiedzieć, czy data jest większa, czy nie, ale istnieje wiele sytuacji do rozważenia, czy trzeba rzeczywiście uzyskać różnicę między dwiema datami.

Innymi słowy-nie próbuj tego wymyślać, chyba że naprawdę nie możesz korzystać z narzędzi innych firm.

 2
Author: Paulius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:59

To nic niesamowitego, ale musiałem zrobić coś takiego dzisiaj i uruchomić go zgodnie z zaplanowanym zadaniem itp.

Plik wsadowy, DelFilesOlderThanNDays.bat poniżej z przykładowym 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
 2
Author: Goran B.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-19 00:01:20

Rozszerzając odpowiedź aku, widzę wiele osób pytających o ścieżki UNC. Po prostu mapowanie ścieżki unc do litery dysku sprawi, że pliki forfiles będą szczęśliwe. Mapowanie i odmapowanie dysków można wykonać programowo, na przykład w pliku wsadowym.

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"

Spowoduje to usunięcie wszystkich plików zrozszerzenia gz, które są starsze niż 7 dni. Jeśli chcesz się upewnić, że Z: nie jest mapowane do niczego innego, możesz zrobić coś prostego jak

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!"
)
 2
Author: Tobias Järvelöv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-14 10:14:47

ROBOCOPY działa dla mnie świetnie. Pierwotnie zasugerował mój Iman. Ale zamiast przenosić pliki/foldery do katalogu tymczasowego, a następnie usuwać zawartość folderu tymczasowego, Przenieś pliki do kosza!!!

To jest kilka linii mojego zapasowego pliku wsadowego na przykład:

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

Czyści wszystko, co starsze niż 15 dni z mojego folderu "Temp" i 30 dni dla wszystkiego, co znajduje się w folderze kopii zapasowej AutoCAD. Używam zmiennych, ponieważ linia może być dość długa i mogę użyć ich ponownie w innych miejscach. Musisz tylko znaleźć ścieżkę dos do kosza powiązaną z Twoim loginem.

To jest na komputerze pracy dla mnie i to działa. Rozumiem, że niektórzy z was mogą mieć bardziej restrykcyjne prawa, ale i tak spróbujcie;) Szukaj w Google wyjaśnień na temat parametrów ROBOCOPY.

Zdrówko!
 1
Author: Shawn Pauliszyn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-15 15:29:17

Rany, już wiele odpowiedzi. Prostą i wygodną trasą jaką znalazłem było wykonanie ROBOCOPA.EXE dwukrotnie w kolejności sekwencyjnej z pojedynczej instrukcji wiersza poleceń systemu Windows przy użyciu & parametr.

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

W tym przykładzie działa poprzez wybranie wszystkich plików (.), które są starsze niż 30 dni i przenoszą je do folderu docelowego. Drugie polecenie robi to samo ponownie z dodaniem PURGE polecenia, co oznacza usunięcie plików w folderze docelowym, które nie istnieje w folderze źródłowym. Tak więc zasadniczo pierwsze polecenie przenosi pliki, a drugie usuwa, ponieważ nie istnieją już w folderze źródłowym podczas wywoływania drugiego polecenia.

Skonsultuj się z dokumentacją ROBOCOPY i użyj przełącznika /L podczas testowania.

 1
Author: GBGOLC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-16 13:33:56

Prawdopodobnie nie znajdziesz całkowicie nieinstalowanego rozwiązania poza skomplikowanym plikiem bat lub skryptem windows. Używam delen, upuszczam go do katalogu systemowego i używam go jak zwykłego polecenia del w dowolnym pliku bat.

 0
Author: bryan314,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-09 01:42:09

Ten zrobił to dla mnie. Działa z datą i można odjąć żądaną kwotę w latach, aby cofnąć się w czasie: {]}

@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

/F w cmd /c del @path /F wymusza usunięcie określonego pliku w niektórych przypadkach plik może być tylko do odczytu.

dateYear jest zmienną roku i tam możesz zmienić odejście do własnych potrzeb

 0
Author: Snickbrack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-19 08:49:54

Mój skrypt do usuwania plików starszych niż określony rok:

@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
 0
Author: efdummy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-15 09:26:25