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

677

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

Podobne rzeczy można zrobić w BASH za pomocą zaledwie kilku linii kodu. Wydaje się, że dla plików wsadowych w systemie Windows można zrobić coś co najmniej zdalnie łatwego. Szukam rozwiązania, które działa w standardowym wierszu polecenia systemu Windows, bez żadnych dodatkowych narzędzi. Proszę nie PowerShell ani Cygwin.

Kibee
źródło
8
Jeff Atwood udzielił odpowiedzi na błąd serwera, który moim zdaniem powinien zostać tutaj udokumentowany. serverfault.com/questions/49614/delete-files-older-than-x-days
Dusty
Nowa metoda oparta na pliku .BAT, która używa tylko wewnętrznych poleceń CMD.EXE, została opublikowana tutaj: stackoverflow.com/questions/9746778/...
Aacini
1
gehrcke.de/timegaps został zaprojektowany do tego celu. Pozwala nawet na bardziej wyrafinowany schemat usuwania: oprócz przechowywania plików z ostatnich 7 dni, pozwala także np. Przechowywać jeden plik dla każdego z ostatnich 8 tygodni, 12, miesięcy, 2 lat.
Dr Jan-Philip Gehrcke

Odpowiedzi:

1071

Cieszyć się:

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

Więcej informacji znajduje się w forfilesdokumentacji .

Więcej dodatków można znaleźć w Indeksie A wiersza poleceń systemu Windows XP .

Jeśli nie masz forfileszainstalowanego na swoim komputerze, skopiuj go z dowolnego systemu 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 systemu Windows i Windows Server mają domyślnie zainstalowane.

W systemie Windows 7 i nowszych (w tym Windows 10):

Składnia nieco się zmieniła. Dlatego zaktualizowane polecenie to:

forfiles /p "C:\what\ever" /s /m *.* /D -<number of days> /C "cmd /c del @path"
aku
źródło
12
Powinien być del @FILE, sprawy mają znaczenie Również sugeruję użycie / c echo @FILE do testowania
Russell Steen
40
@ Russell: @PATH to pełna ścieżka, w tym nazwa. @FILE to tylko nazwa, więc jeśli masz do czynienia z podfolderami, to nie zadziała.
gregmac,
86
Zauważ, że jeśli chcesz mieć pliki starsze niż 10 dni, musisz podać -d „-10”. -ve oznacza „starszy niż”, + ve oznacza „nowszy niż”. Możesz również określić format DDMMRR lub -DDMMRR jako parametr na -d.
gregmac,
42
Użyłem tej składni na Win Server 2008: forfiles / P "C: \ Mysql_backup" / S / M * .sql / D -30 / C "cmd / c del @PATH"
jman
9
Ta odpowiedź działa, gdy „starszy niż 7 dni” jest zdefiniowany jako „zmodyfikowany więcej niż 7 dni temu” niż „utworzony więcej niż 7 dni temu”. Jak można to osiągnąć?
TimS
76

Uruchom następujące polecenia :

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

Przenieś wszystkie pliki (używając / mov, który przenosi pliki, a następnie usuwa je, w przeciwieństwie do / move, który przenosi całe pliki, które są następnie usuwane) za pomocą robocopy w inne miejsce, a następnie wykonaj polecenie usuwania na tej ścieżce, a ty wszystko dobrze.

Również jeśli masz katalog z dużą ilością danych, możesz użyć /mirprzełącznika

Iman
źródło
5
W przeważającej części jest to dość niepraktyczna odpowiedź. Jeśli mam katalog z dużą ilością danych, nie będzie działać dobrze.
Wybrałbym
5
@ adamb0mb nie jest to w żaden sposób niepraktyczne - jeśli „destination” znajduje się w tym samym systemie plików co „source” , operacja przenoszenia jest dość lekka. Ponieważ robocopy jest naprawdę solidny, w rzeczywistości będzie działał dla dowolnego rozmiaru katalogu, niejasnych nazw plików, zasadniczo dowolnych długości ścieżek i dołączał katalogi, jeśli jest to potrzebne - czegoś, czego z pewnością nie można powiedzieć o wielu innych narzędziach systemu Windows. Chciałbym użyć rd /s /q c:\destinationzamiast delpolecenia, a nawet użyć innego robocopy /mir c:\emptydir c:\destinationuruchomienia, aby opróżnić katalog, jeśli oczekujesz problemów z nazwami plików.
syneticon-dj,
12
Plus, robocopy obsługuje ścieżki UNC - co forfilesz przyjętej odpowiedzi nie da rady.
syneticon-dj
3
Moje myśli brzmiały mniej więcej tak: „Moje pliki są już tam, gdzie chcę. Nie chcę ich przenosić”. „Usuwanie plików jest logicznie tym, co robisz, więc zrób to. Nie przeciążaj Robocopy, aby to zrobić”
adamb0mb
3
Polecam ten jeden wiersz do przeglądania wszystkich plików C:\teststarszych niż 7 dni. Aby usunąć pliki, zmień echona del:forfiles /p "C:\test" /m "*.*" /c "cmd /c echo @file" /D -7
PowerUser
25

Ok trochę się nudziłem i wymyśliłem to, które zawiera moją wersję zamiennika epoki Linuksa biedaka, ograniczoną 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

STOSOWANIE

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

set dSource=C:\temp : To jest katalog początkowy do sprawdzania plików.

UWAGI

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

Zmiana :

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

do czegoś takiego:

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

więc pliki zostaną faktycznie usunięte

Luty : jest zakodowany na stałe do 28 dni. Bissextile lata to naprawdę piekło. jeśli ktoś ma pomysł, który nie dodałby 10 linii kodu, śmiało pisz dalej, więc dodaję go do mojego kodu.

epoka : Nie brałem pod uwagę czasu, ponieważ potrzeba jest usunięcia plików starszych niż określona data, zajęcie godzin / minut spowodowałoby usunięcie plików z dnia, który miał być zachowany.

OGRANICZENIE

epoka przyjmuje za pewnik, że twój krótki format daty to RRRR-MM-DD. Musiałby zostać dostosowany do innych ustawień lub oceny w czasie wykonywania (czytaj sShortTime, konfiguracja związana z użytkownikiem, skonfiguruj odpowiednią kolejność pól w filtrze i użyj filtru, aby wyodrębnić poprawne dane z argumentu).

Czy wspominałem, że nienawidzę automatycznego formatowania tego edytora? usuwa puste linie, a kopiowanie i wklejanie to piekło.

Mam nadzieję, że to pomoże.

Sójka
źródło
4
+1 za nieniszczący kod, postaram się o tym pamiętać, gdy sam podaję przykłady kodu.
Haugholt,
5
Dość późno i całkowicie niezwiązany, ale 7daysclean.cmdbrzmi jak niesamowite imię dla zespołu Synth-Punk.
Flonk
21
forfiles /p "v:" /s /m *.* /d -3 /c "cmd /c del @path"

Powinieneś to zrobić /d -3(3 dni wcześniej) To działa dobrze dla mnie. Tak więc wszystkie skomplikowane partie mogą znajdować się w koszu. Również forfilesnie obsługują ścieżek UNC, więc nawiązać połączenie sieciowe z napędzające.

Arno Jansen
źródło
3
Ten sam błąd, co w innych odpowiedziach (w tym w zaakceptowanej). Skąd wziął się ten dziwny nawyk sprecyzowania *.*? Symbol wieloznaczny *.*nie pasuje do wszystkich plików w systemie Windows. Pasuje tylko do plików z .ich nazwami. OP nigdy nie powiedział nic o wymaganiu .w nazwie pliku. Właściwym parametrem jest /M *, ale i tak jest to ustawienie domyślne. W ogóle nie ma takiej potrzeby /M.
AnT
@AnT: Jesteś pewien? Myślę, że *.*zachowuje się dokładnie tak, jak *w systemie Windows. W rzeczywistości właśnie wypróbowałem go na swoim komputerze i dir *.*rzeczywiście wymieniłem test fileplik bez rozszerzenia.
Andreas Rejbrand
1
@Andreas Rejbrand: Uważam to również za zaskakujące, ale leczenie *.*jest niespójne między, powiedzmy, dira -mopcją forfiles. -m *.*Maska rzeczywiście pominąć bez rozszerzeń nazw plików, jak stwierdziłem w moim komentarzu powyżej (spróbować samemu). Zabawne jest to, że dokumentacja MS wyraźnie stwierdza, że -m *.*jest to ustawienie domyślne. Jeśli jednak wypróbujesz to w prawdziwym życiu, zobaczysz, że domyślnie jest tak naprawdę -m *- wszystkie pliki są iterowane.
AnT
1
Ta strona dokumentacji MS - technet.microsoft.com/en-us/library/cc753551(v=ws.11).aspx - zawiera dużą liczbę błędów (np. W przykładach), ponieważ autor dokumentu błędnie uważał, że *.*maska ​​została zastosowana do wszystkich plików. Moje retoryczne pytanie dotyczące „tego dziwnego nawyku” było rzeczywiście nieuzasadnione, ponieważ traktowanie *.*i *równoważność jest od dawna konwencją Windows. Jednak /mopcja forfilesz jakiegoś powodu narusza tę konwencję.
AnT
1
Tło na 5 symbolach
MSalters
18

Zobacz 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"

Spowoduje to usunięcie plików starszych niż podana data. Jestem pewien, że można go zmodyfikować, aby cofnął się o siedem dni od bieżącej daty.

aktualizacja: Zauważyłem, że HerbCSO ulepszyło powyższy skrypt. Zamiast tego zalecam użycie jego wersji .

e.James
źródło
12

Moje polecenie jest

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

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

też forfiles /?dla mnie też nie działa, ale forfiles(bez „?”) działało dobrze.

I jedyne pytanie, jakie mam: jak dodać wiele masek (na przykład „ .log | .bak”)?

Wszystko to dotyczy pliku forfiles.exe, który pobrałem tutaj (na Win XP)

Ale jeśli używasz serwera Windows, plik forfiles.exe powinien już tam być i różni się od wersji ftp. Dlatego powinienem zmodyfikować polecenie.

W systemie Windows Server 2003 używam tego polecenia:

forfiles -p "d:\Backup" -s -m *.log -d -15 -c "cmd /c del @PATH"
Sergo
źródło
9

Bardzo często pojawiają się pytania dotyczące daty / godziny, które należy rozwiązać za pomocą pliku wsadowego. Ale interpreter cmd.exe wiersza poleceń nie ma funkcji do obliczania daty / godziny. Wiele dobrych działających rozwiązań korzystających z dodatkowych aplikacji konsolowych lub skryptów zostało już opublikowanych tutaj, na innych stronach Stack Overflow i na innych stronach internetowych.

Wspólne dla operacji opartych na dacie / godzinie jest wymóg konwersji ciągu daty / godziny na sekundy od określonego dnia. Bardzo często jest 1970-01-01 00:00:00 UTC. Ale każdy późniejszy dzień może być również wykorzystany w zależności od zakresu dat wymaganego do obsługi określonego zadania.

Jay opublikował 7daysclean.cmd zawierający szybkie rozwiązanie „data do sekund” dla interpretera cmd.exe z wiersza poleceń . Ale nie bierze się pod uwagę poprawnych lat przestępnych. JR opublikował dodatek uwzględniający dzień przestępny w bieżącym roku, ale ignoruje inne lata przestępne od roku bazowego, tj. Od 1970 r.

Używam od 20 lat tabel statycznych (tablic) utworzonych raz z małą funkcją C do szybkiego uzyskiwania liczby dni, w tym dni przestępnych od 1970-01-01 w funkcjach konwersji daty / godziny w moich aplikacjach napisanych w C / C ++.

Ta bardzo szybka metoda tabeli może być również używana w kodzie wsadowym za pomocą polecenia FOR . Postanowiłem więc zakodować podprogram partii, GetSecondsktóry oblicza liczbę sekund od 1970-01-01 00:00:00 UTC dla ciągu daty / godziny przekazanego do tej procedury.

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

Po pierwsze, tabele:

  1. Dni od 1970-01-01 00:00:00 UTC na każdy rok, w tym dni przestępne.

    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ę 1970-01-01 jest możliwe tylko przy użyciu 32-bitowej zmiennej bez znaku, tj. Bez znaku długiej (lub bez znaku int) w C / C ++.

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

  2. Informacje o roku przestępnym (Nie / Tak) za lata 1970–2010.

    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 tabel.

Proszę o uwagę!

Format ciągów daty i godziny zależy od regionu i ustawień systemu Windows. Ograniczniki i kolejność żetonów przypisanych zmiennej środowiska Day, Monthi Yearnajpierw za pętląGetSeconds musi być dostosowana do lokalnego formatu daty / czasu w razie potrzeby.

Konieczne jest dostosowanie ciągu daty zmiennej środowiskowej, jeśli format daty w zmiennej środowiskowej DATE różni się od formatu daty używanego przez polecenie FOR on %%~tF.

Na przykład, gdy %DATE%rozwija się do Sun 02/08/2015while, %%~tFrozwija się 02/08/2015 07:38 PMdo kodu poniżej, można użyć z modyfikacją wiersza 4 do:

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

Powoduje to przejście do podprogramu po prostu 02/08/2015- ciąg daty bez 3 liter skrótu dnia tygodnia i znak odstępu.

Alternatywnie można zastosować następujące informacje, aby przekazać aktualną datę w poprawnym formacie:

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

Teraz ostatnie 10 znaków z ciągu daty jest przekazywanych do funkcji, GetSecondsa zatem nie ma znaczenia, czy ciąg daty zmiennej środowiskowej DATE jest z, czy bez dnia tygodnia, o ile dzień i miesiąc są zawsze z 2 cyframi w oczekiwanej kolejności, tj. W formacie dd/mm/yyyy lub dd.mm.yyyy.

Oto kod wsadowy z objaśnieniem komentarzy, które po prostu wypisują, który plik należy usunąć, a który przechowywać w C:\Tempdrzewie folderów, patrz kod pierwszej pętli FOR .

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

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

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


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

:GetSeconds

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

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

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

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

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

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

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

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

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

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

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

rem Exit this subroutine
goto :EOF

Dla optymalnej wydajności najlepiej byłoby usunąć wszystkie komentarze, tj. Wszystkie wiersze zaczynające się od rem po 0-4 wiodących spacji.

A tablice można również zmniejszyć, tj. Zmniejszając zakres czasu od 1980-01-01 00:00:00 do 2038-01-19 03:14:07, jak obecnie obsługuje powyższy kod partii, na przykład do 2015-01 -01 do 2019-12-31, ponieważ poniższy kod naprawdę usuwa pliki starsze niż 7 dni C:\Temp drzewie folderów.

Ponadto poniższy kod partii jest zoptymalizowany do formatu 24-godzinnego.

@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ć więcej informacji na temat formatów daty i godziny oraz porównań czasu pliku w systemie Windows, zobacz moją odpowiedź na temat Sprawdź, czy plik jest starszy niż 4 godziny w pliku wsadowym, z dużą ilością dodatkowych informacji o czasach plików.

Mofi
źródło
9

Skopiuj ten kod i zapisz go jako DelOldFiles.vbs.

ZASTOSOWANIE W CMD: cscript //nologo DelOldFiles.vbs 15

15 oznacza usuwanie plików starszych niż 15 dni wcześniej.

  '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
Paryż
źródło
8

W systemie Windows Server 2008 R2:

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

Spowoduje to usunięcie wszystkich plików .sql starszych niż 90 dni.

NotJustClarkKent
źródło
7

Użyj forfiles.

Istnieją różne wersje. Wcześni używają parametrów stylu uniksowego.

Moja wersja (dla serwera 2000 - uwaga po spacji po przełącznikach) -

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

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

i dodaj go do C: \ WINDOWS \ system32

Aidan Ewen
źródło
11
@ Kibbee to nie ta sama odpowiedź, ale inna składnia. To była genialna próba pomocy. Znając bardzo niewiele z wiersza poleceń systemu Windows, spędziłem godziny frustracji, żeby to zadziałało. Kluczowe dla mnie informacje to fakt, że istnieją różne wersje (o różnej składni) i że muszę usunąć spacje. Żadna z tych rzeczy nie została ujęta w oryginalnej odpowiedzi. (Skomentowałbym odpowiedź, ale nie mam przywilejów
Aidan Ewen
Ten sam błąd, co w innych odpowiedziach (w tym w zaakceptowanej). Symbol wieloznaczny *.*w forfilesnie pasuje do wszystkich plików. Dopasowuje tylko pliki z .ich nazwami (tj. Pliki z rozszerzeniami). OP nigdy nie powiedział nic o wymaganiu .w nazwie pliku. Właściwym parametrem jest /M *, ale i tak jest to ustawienie domyślne. W ogóle nie ma takiej potrzeby /M.
ANT
7

W przypadku systemu Windows 2012 R2 będą działać następujące czynności:

    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"
Viktor Ka
źródło
Działa to nawet w systemie Windows Server 2008 i nowszych oraz Windows 7.
kwrl
6

IMO, JavaScript stopniowo staje się uniwersalnym standardem skryptów: prawdopodobnie jest dostępny w większej liczbie produktów niż jakikolwiek inny język skryptowy (w Windows jest dostępny za pomocą Windows Scripting Host). Muszę wyczyścić stare pliki w wielu folderach, więc oto 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 wyczyścić każdy folder, po prostu dodaj kolejne wywołanie do funkcji clearFolder (). Ten konkretny kod zachowuje również pliki exe i dll oraz czyści również podfoldery.

Graham Laight
źródło
6

Co powiesz na tę modyfikację na 7daysclean.cmd aby uwzględnić rok przestępny?

Można to zrobić za pomocą mniej niż 10 linii 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

Edytuj przez Mofi:

Powyższy warunek, do którego przyczynił się JR, ocenia się zawsze na false powodu niepoprawnej składni.

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

Działającym kodem, który należy wziąć pod uwagę dzień przestępny - tylko w bieżącym roku - w pliku wsadowym 7daysclean.cmd opublikowanym przez Jay byłoby:

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
JR
źródło
5

Czy mogę dodać pokorny wkład do tego i tak już cennego wątku. Zauważyłem, że inne rozwiązania mogą pozbyć się rzeczywistego tekstu błędu, ale ignorują% ERRORLEVEL%, który sygnalizuje błąd w mojej aplikacji. I słusznie chcę% ERRORLEVEL%, o ile nie jest to błąd „Nie znaleziono plików”.

Kilka przykładów:

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

Użycie programu oneliner do zwrócenia błędu lub błędu ERRORLEVEL:

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

Użycie programu oneliner do utrzymania zerowej wartości ERRORLEVEL na zero dla sukcesu w kontekście pliku wsadowego pośród innego kodu (ver> nul resetuje ERRORLEVEL):

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

W przypadku zadania CmdExec agenta programu SQL Server wylądowałem na następujących tematach. Nie wiem, czy to błąd, ale CmdExec w kroku rozpoznaje tylko pierwszy wiersz 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%
Żądło
źródło
5

Boże, już wiele odpowiedzi. Prostą i wygodną trasą, którą znalazłem, było dwukrotne uruchomienie ROBOCOPY.EXE w jednej kolejności z jednej instrukcji wiersza poleceń systemu Windows za pomocą parametru & .

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 on przez wybranie wszystkich plików ( . ) Starszych niż 30 dni i przeniesienie ich 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 istnieją w folderze źródłowym. Zasadniczo pierwsze polecenie PRZENIESIA pliki, a drugie USUWA, ponieważ nie są one już dostępne w folderze źródłowym po wywołaniu drugiego polecenia.

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

GBGOLC
źródło
4

Jeśli masz zestaw zasobów XP, możesz użyć robocopy, aby przenieść wszystkie stare katalogi do jednego katalogu, a następnie użyj 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
neuracnu
źródło
4

Myślę, że odpowiedź e.James jest dobra, ponieważ działa z niezmodyfikowanymi wersjami systemu Windows już w systemie Windows 2000 SP4 (i być może wcześniej), ale wymagała zapisu do pliku zewnętrznego. Oto zmodyfikowana wersja, która nie tworzy zewnętrznego pliku tekstowego, zachowując zgodność:

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ć prawdziwym w stosunku do pierwotnego pytania, oto skrypt, który wykonuje CAŁĄ matematykę, jeśli nazwiesz ją 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 łączna liczba dni, które upłynęły od 0/0/0 (po czym zwraca lata ujemne).

UWAGA: matematyka idzie tylko w jedną stronę; nie może poprawnie pobrać przyszłych dat z negatywnych danych wejściowych (spróbuje, ale prawdopodobnie minie ostatni dzień miesiąca).

Lectrode
źródło
3

Być może będziesz w stanie to zrobić. Możesz spojrzeć na to pytanie , na prostszy przykład. Złożoność przychodzi, gdy zaczynasz porównywać daty. Może być łatwo stwierdzić, czy data jest dłuższa, czy nie, ale istnieje wiele sytuacji, które należy rozważyć, jeśli naprawdę potrzebujesz uzyskać różnicę między dwiema datami.

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

Paulius
źródło
3

to nie jest nic niesamowitego, ale musiałem dziś zrobić coś takiego i uruchomić go jako zaplanowane zadanie 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
Goran B.
źródło
3

Rozwijając odpowiedź aku, widzę wiele osób pytających o ścieżki UNC. Proste mapowanie ścieżki unc na literę dysku sprawi, że pliki forfile będą szczęśliwe. Mapowanie i usuwanie mapowania dysków można na przykład wykonać programowo 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 z rozszerzeniem .gz, które są starsze niż 7 dni. Jeśli chcesz się upewnić, że Z: nie jest mapowany na nic innego przed użyciem, 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!"
)
Tobias Järvelöv
źródło
3

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

Oto kilka wierszy mojego pliku wsadowego kopii zapasowej, 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 starsze niż 15 dni z mojego folderu „Temp” i 30 dni na wszystko w moim folderze kopii zapasowej AutoCAD. Używam zmiennych, ponieważ linia może być dość długa i mogę ich ponownie użyć w innych lokalizacjach. Musisz tylko znaleźć ścieżkę dos do kosza związanego z logowaniem.

To jest na moim komputerze roboczym i działa. Rozumiem, że niektórzy z was mogą mieć bardziej restrykcyjne prawa, ale i tak spróbujcie;) Wyszukaj w Google wyjaśnienia dotyczące parametrów ROBOCOPY.

Twoje zdrowie!

Shawn Pauliszyn
źródło
1
Istniejąca druga najbardziej uprzywilejowana odpowiedź również popiera RoboCopy. To prawda, że ​​używasz nieco innych opcji, ale jest to zbliżone do istniejącej odpowiedzi.
Jonathan Leffler,
2
Ten post ma nową zawartość - przenoszenie plików do kosza. Nie zostało to jeszcze zaproponowane w Robocopy i całkowicie odpowiada na oryginalny post za pomocą wbudowanego polecenia jednowierszowego. Działa lepiej niż łączenie poleceń „DEL” i „RMDIR”, ponieważ pliki można przywrócić z kosza. Hej, wciąż tu jestem nowy - daj mi spokój;)
Shawn Pauliszyn
2

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
efdummy
źródło
1

Ten zrobił to dla mnie. Działa z datą i możesz 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

/Fwcmd /c del @path /F siłach plik specyficzny zostać usunięte w niektórych przypadkach plik może być tylko do odczytu.

dateYearjest rok zmienna i nie można zmienić odejmowania do własnych potrzeb

Snickbrack
źródło