Вопрос

Я ищу способ удалить все файлы старше 7 дней в пакетном файле.Я поискал в Интернете и нашел несколько примеров с сотнями строк кода, а также другие, требующие установки дополнительных утилит командной строки для выполнения задачи.

Подобные вещи могут быть сделано в BASH всего за пару строк кода.Кажется, что для пакетных файлов в Windows можно сделать что-то хотя бы отдаленно простое.Я ищу решение, которое работает в стандартной командной строке Windows без каких-либо дополнительных утилит.Пожалуйста, не используйте PowerShell или Cygwin.

Это было полезно?

Решение

Наслаждаться:

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

Видеть форфайловая документация Больше подробностей.

Еще больше вкусностей см. Индекс A-Z командной строки Windows XP..

Если у вас нет forfiles установлен на вашем компьютере, скопируйте его из любого Windows Сервер 2003 на ваш компьютер с Windows XP по адресу %WinDir%\system32\.Это возможно, поскольку EXE-файл полностью совместим между Windows Server 2003 и Windows XP.

В более поздних версиях Windows и Windows Server он установлен по умолчанию.

Для Windows 7 и более поздних версий (включая Windows 10):

Синтаксис немного изменился.Поэтому обновленная команда:

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

Другие советы

Запустите следующее команды:

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

Переместите все файлы (используя /mov, который перемещает файлы, а затем удаляет их, в отличие от /move, который перемещает целые деревья файлов, которые затем удаляются) с помощью robocopy в другое место, а затем выполните команду удаления по этому пути, и все готово. хороший.

Также, если у вас есть каталог с большим количеством данных, вы можете использовать /mir выключатель

Оку было немного скучно, и он придумал это, которое содержит мою версию замены эпохи Linux для бедняков, ограниченную для ежедневного использования (без сохранения времени):

7daysclean.cmd

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

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

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

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

ИСПОЛЬЗОВАНИЕ

set /a strip=day*7 :Изменять 7 за количество дней хранения.

set dSource=C:\temp :Это начальный каталог для проверки файлов.

ПРИМЕЧАНИЯ

Это неразрушающий код, он отобразит то, что могло бы произойти.

Изменять :

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

что-то вроде:

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

поэтому файлы фактически удаляются

февраль:жестко запрограммирован на 28 дней.Биссексуальные годы – это чертовски приятно прибавлять, правда.Если у кого-то есть идея, которая не требует добавления 10 строк кода, опубликуйте ее, чтобы я добавил ее в свой код.

эпоха:Я не учел время, так как необходимо удалить файлы старше определенной даты, часы/минуты привели бы к удалению файлов за день, который предназначался для хранения.

ОГРАНИЧЕНИЕ

эпоха считает само собой разумеющимся, что ваш краткий формат даты — ГГГГ-ММ-ДД.Его необходимо будет адаптировать для других настроек или оценки во время выполнения (прочитайте sShortTime, пользовательскую конфигурацию, настройте правильный порядок полей в фильтре и используйте фильтр для извлечения правильных данных из аргумента).

Я уже упоминал, что ненавижу автоматическое форматирование в этом редакторе?он удаляет пустые строки, а копипаста - это ад.

Надеюсь, это поможет.

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

Ты должен сделать /d -3 (3 дня назад) У меня это работает нормально.Таким образом, все сложные партии могут оказаться в мусорном ведре.Также forfiles не поддерживают пути UNC, поэтому подключитесь к конкретному диску по сети.

Взгляни на мой отвечать к аналогичный вопрос:

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"

При этом удаляются файлы старше заданной даты.Я уверен, что его можно изменить, чтобы вернуться на семь дней назад от текущей даты.

обновлять: Я заметил, что HerbCSO улучшил приведенный выше сценарий.Я рекомендую использовать его версия вместо.

Моя команда

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

@PATH - в моем случае это просто путь, поэтому мне пришлось использовать @PATH\@FILE

также forfiles /? у меня тоже не работает, но forfiles (без "?") работало нормально.

И единственный у меня вопрос:как добавить несколько масок (например ".log|.бак")?

Все это относительно forfiles.exe, которое я скачал здесь (на Win XP)

Но если вы используете сервер Windows, файл forfiles.exe уже должен быть там, и он отличается от версии ftp.Вот почему мне следует изменить команду.

Для Windows Server 2003 я использую эту команду:

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

Для Windows Server 2008 R2:

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

Это удалит все .sql файлы старше 90 дни.

Скопируйте этот код и сохраните его как DelOldFiles.vbs.

ИСПОЛЬЗОВАНИЕ ТОЛЬКО В КОМАНДНОЙ СТРОКЕ:cscript DelOldFiles.vbs 15

15 означает удаление файлов старше 15 дней назад.

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

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

    DeleteOlderFiles(".")
 'to here

Используйте форфайлы.

Есть разные версии.Ранние используют параметры стиля Unix.

Моя версия (для сервера 2000 - обратите внимание, после переключателей нет пробела) -

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

Чтобы добавить файлы файлов в XP, скачайте exe-файл с сайта ftp://ftp.microsoft.com/ResKit/y2kfix/x86/

и добавьте его в C:\WINDOWS\system32.

Для Windows 2012 R2 будет работать следующее:

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

чтобы увидеть файлы, которые будут удалены, используйте это

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

ИМХО, JavaScript постепенно становится универсальным стандартом сценариев:он, вероятно, доступен в большем количестве продуктов, чем любой другой язык сценариев (в Windows он доступен с помощью Windows Scripting Host).Мне нужно очистить старые файлы во многих папках, поэтому для этого есть функция JavaScript:

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

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

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

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

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

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

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

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

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

Чтобы очистить каждую папку, просто добавьте еще один вызов функцииclearFolder().Этот конкретный код также сохраняет файлы exe и dll, а также очищает подпапки.

Как насчет этой модификации на 7daysclean.cmd учитывать високосный год?

Это можно сделать менее чем за 10 строк кода!

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

Редактирование Мофи:

Условие выше, вызванное Дж.Р. всегда оценивается как ЛОЖЬ из-за неверного синтаксиса.

И Month GEQ 2 неверно еще и потому, что прибавление 86400 секунд для еще одного дня необходимо в високосном году производить только для месяцев с марта по декабрь, но не для февраля.

Рабочий код для учета високосного дня (только в текущем году) в пакетном файле 7daysclean.cmd Сообщение от Джей было бы:

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

Очень часто возникают вопросы, связанные с относительной датой и временем, которые необходимо решить с помощью пакетного файла.Но интерпретатор командной строки cmd.exe не имеет функции для расчета даты/времени.Множество хороших рабочих решений с использованием дополнительных консольных приложений или скриптов уже опубликовано здесь, на других страницах Stack Overflow и на других сайтах.

Общим для операций, основанных на дате/времени, является требование преобразовать строку даты/времени в секунды, прошедшие с определенного дня.Очень часто встречается 1970-01-01 00:00:00 UTC.Но можно также использовать любой более поздний день в зависимости от диапазона дат, необходимого для поддержки конкретной задачи.

Джей опубликовано 7daysclean.cmd содержит быстрое решение «дата в секундах» для интерпретатора командной строки cmd.exe.Но при этом не учитываются високосные годы. Дж.Р. опубликовал добавить для учета високосного дня в текущем году, но игнорирования других високосных лет, начиная с базового года, т.е.с 1970 года.

Я использую уже 20 лет статические таблицы (массивы), созданные один раз с помощью небольшой функции C, для быстрого получения количества дней, включая високосные дни, с 1970-01-01, в функциях преобразования даты и времени в моих приложениях, написанных на C/C++.

Этот очень быстрый табличный метод можно использовать и в пакетном коде, используя ДЛЯ команда.Поэтому я решил написать пакетную подпрограмму GetSeconds который вычисляет количество секунд с 1970-01-01 00:00:00 UTC для строки даты/времени, переданной в эту подпрограмму.

Примечание: Дополнительные секунды не учитываются, поскольку файловые системы Windows также не поддерживают дополнительные секунды.

Сначала таблицы:

  1. Дней с 1970-01-01 00:00:00 UTC для каждого года, включая високосные дни.

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

    Вычисление секунд для года с 2039 по 2106 год с эпохой, начинающейся с 1 января 1970 года, возможно только с использованием беззнаковой 32-битной переменной, т.е.unsigned long (или unsigned int) в C/C++.

    Но cmd.exe используйте для математических выражений 32-битную переменную со знаком.Следовательно, максимальное значение — 2147483647 (0x7FFFFFFF), что соответствует 19.01.2038 03:14:07.

  2. Информация о високосном году (Нет/Да) за период с 1970 по 2106 год.

    1970 - 1989: N N Y N N N Y N N N Y N N N Y N N N Y N
    1990 - 2009: N N Y N N N Y N N N Y N N N Y N N N Y N
    2010 - 2029: N N Y N N N Y N N N Y N N N Y N N N Y N
    2030 - 2049: N N Y N N N Y N N N Y N N N Y N N N Y N
    2050 - 2069: N N Y N N N Y N N N Y N N N Y N N N Y N
    2070 - 2089: N N Y N N N Y N N N Y N N N Y N N N Y N
    2090 - 2106: N N Y N N N Y N N N N N N N Y N N
                                     ^ year 2100
    
  3. Количество дней до первого числа каждого месяца в текущем году.

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

Преобразовать дату в количество секунд с 1 января 1970 г. с помощью этих таблиц довольно просто.

Внимание, пожалуйста!

Формат строк даты и времени зависит от региона Windows и языковых настроек.Разделители и порядок токенов, назначенных переменным среды. Day, Month и Year во-первых ДЛЯ петля из GetSeconds при необходимости необходимо адаптировать к местному формату даты/времени.

Необходимо адаптировать строку даты переменной среды, если формат даты в переменной среды ДАТА отличается от формата даты, используемого командой ДЛЯ на %%~tF.

Например, когда %DATE% расширяется до Sun 02/08/2015 пока %%~tF расширяется до 02/08/2015 07:38 PM приведенный ниже код можно использовать, изменив строку 4 на:

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

Это приводит к переходу к подпрограмме просто 02/08/2015 - строка даты без трех букв обозначения дня недели и разделительного пробела.

В качестве альтернативы для передачи текущей даты в правильном формате можно использовать следующее:

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

Теперь в функцию передаются последние 10 символов строки даты. GetSeconds и поэтому не имеет значения, является ли строка даты переменной среды ДАТА с днем ​​недели или без него, если день и месяц всегда состоят из двух цифр в ожидаемом порядке, т.е.в формате dd/mm/yyyy или dd.mm.yyyy.

Вот пакетный код с поясняющими комментариями, который просто выводит, какой файл удалить, а какой оставить. C:\Temp дерево папок, см. код первого ДЛЯ петля.

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

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

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


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

:GetSeconds

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

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

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

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

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

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

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

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

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

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

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

rem Exit this subroutine
goto :EOF

Для оптимальной производительности лучше всего удалить все комментарии, т.е.все строки, начинающиеся с рем после 0-4 ведущих пробелов.

А массивы можно сделать и меньше, т.е.уменьшение временного диапазона с 1980-01-01 00:00:00 до 2038-01-19 03:14:07, как это в настоящее время поддерживается приведенным выше кодом пакета, например, с 2015-01-01 по 2019-12-31, как приведенный ниже код действительно удаляет файлы старше 7 дней в C:\Temp дерево папок.

Кроме того, приведенный ниже пакетный код оптимизирован для 24-часового формата времени.

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

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

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

Для получения дополнительной информации о форматах даты и времени и сравнении времени файлов в Windows см. мой ответ на Узнайте, старше ли файл более 4 часов в пакетном файле с большим количеством дополнительной информации о времени файла.

Могу ли я внести скромный вклад в эту и без того ценную тему.Я обнаружил, что другие решения могут избавиться от фактического текста ошибки, но игнорируют %ERRORLEVEL%, который сигнализирует о сбое в моем приложении.И я законно хочу %ERRORLEVEL%, если это не ошибка «Файлы не найдены».

Некоторые примеры:

Отладка и устранение ошибки конкретно:

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

Использование однострочника для возврата успеха или неудачи ERRORLEVEL:

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

Использование однострочника для сохранения ERRORLEVEL на нулевом уровне для успеха в контексте пакетного файла среди другого кода (ver > nul сбрасывает ERRORLEVEL):

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

На этапе задания CmdExec агента SQL Server я получил следующее.Я не знаю, ошибка ли это, но CmdExec на этом этапе распознает только первую строку кода:

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

Если у вас есть набор ресурсов XP, вы можете использовать robocopy, чтобы переместить все старые каталоги в один каталог, а затем использовать rmdir, чтобы удалить только этот каталог:

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

Я думаю ответ e.Джеймса хорош, поскольку работает с немодифицированными версиями Windows, начиная с Windows 2000 SP4 (и, возможно, раньше), но требует записи во внешний файл.Вот модифицированная версия, которая не создает внешний текстовый файл, сохраняя при этом совместимость:

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

Чтобы быть верным исходному вопросу, вот он в скрипте, который выполняет ВСЕ математические вычисления за вас, если вы вызываете его с количеством дней в качестве параметра:

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

ПРИМЕЧАНИЕ:В приведенном выше коде учитываются високосные годы, а также точное количество дней в каждом месяце.Единственным максимумом является общее количество дней, прошедших с 0/0/0 (после этого возвращается отрицательное число лет).

ПРИМЕЧАНИЕ:Математика идет только в одну сторону;он не может правильно получить будущие даты на основе отрицательных входных данных (он попытается, но, скорее всего, пройдет мимо последнего дня месяца).

Возможно, у тебя получится это осуществить.Вы можете взглянуть на этот вопрос, для более простого примера.Сложность возникает, когда вы начинаете сравнивать даты.Определить, больше дата или нет, может быть легко, но есть много ситуаций, которые следует учитывать, если вам действительно нужно получить разницу между двумя датами.

Другими словами – не пытайтесь изобрести это, если только вы действительно не умеете использовать сторонние инструменты.

в этом нет ничего удивительного, но мне нужно было сделать что-то подобное сегодня и запустить это как запланированное задание и т. д.

Пакетный файл DelFilesOlderThanNDays.bat ниже с примером выполнения с параметрами:

DelFilesOlderThanNDays.bat 7 C:\dir1\dir2\dir3\logs *.бревно

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

Расширяя ответ Аку, я вижу, что многие люди спрашивают о путях UNC.Простое сопоставление unc-пути с буквой диска сделает forfiles счастливыми.Сопоставление и отключение дисков можно выполнить, например, программно в пакетном файле.

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"

При этом будут удалены все файлы с расширением .gz старше 7 дней.Если вы хотите убедиться в Z:не сопоставлен ни с чем другим, прежде чем использовать его, вы можете сделать что-то простое, например

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

Господи, уже много ответов.Я нашел простой и удобный способ — дважды последовательно выполнить ROBOCOPY.EXE из одной инструкции командной строки Windows, используя команду & параметр.

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

В этом примере это работает путем выбора всех файлов (.), которым больше 30 дней, и переместите их в целевую папку.Вторая команда снова делает то же самое с добавлением УДАЛЯТЬ команда, которая означает удаление файлов в целевой папке, которых нет в исходной папке.По сути, первая команда ПЕРЕМЕЩАЕТ файлы, а вторая УДАЛЯЕТ, потому что они больше не существуют в исходной папке при вызове второй команды.

Обратитесь к документации ROBOCOPY и используйте ключ /L при тестировании.

РОБОКОПИЯ у меня отлично работает.Изначально предложил мой Иман.Но вместо перемещения файлов/папок во временный каталог и последующего удаления содержимого временной папки, переместите файлы в корзину!!!

Например, это несколько строк моего пакетного файла резервной копии:

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

Он удаляет все файлы старше 15 дней из моей папки Temp и 30 дней из папки резервных копий AutoCAD.Я использую переменные, потому что строка может оказаться довольно длинной, и я могу повторно использовать их для других мест.Вам просто нужно найти путь к корзине, связанный с вашим логином.

У меня это на рабочем компьютере и все работает.Я понимаю, что у некоторых из вас могут быть более ограничительные права, но все равно попробуйте;) Поищите в Google пояснения по параметрам ROBOCOPY.

Ваше здоровье!

Этот сделал это за меня.Он работает с датой, и вы можете вычесть желаемую сумму в годах, чтобы вернуться во времени:

@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 в cmd /c del @path /F принудительно удаляет конкретный файл, в некоторых случаях файл может быть доступен только для чтения.

тот dateYear это год. Переменная, и здесь вы можете изменить вычитание в соответствии со своими потребностями.

Мой скрипт для удаления файлов старше определенного года:

@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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top