windows - ملف دفعي لحذف الملفات الأقدم من N أيام




date batch-file (16)

أصبحت IMO، JavaScript تدريجياً معيارًا عالميًا للبرمجة: ربما تكون متاحة في منتجات أكثر من أي لغة برمجة نصية أخرى (في Windows ، تكون متوفرة باستخدام Windows Scripting Host). لا بد لي من تنظيف الملفات القديمة في الكثير من المجلدات ، لذلك هنا وظيفة جافا سكريبت للقيام بذلك:

// 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 وينظف المجلدات الفرعية أيضًا.

أنا أبحث عن طريقة لحذف كافة الملفات الأقدم من 7 أيام في ملف دفعي. لقد بحثت في جميع أنحاء الويب ، ووجدت بعض الأمثلة مع مئات من أسطر الكود ، وغيرها من الأشياء التي تطلب تركيب أدوات مساعدة إضافية لسطر الأوامر لإنجاز المهمة.

يمكن إجراء أشياء مشابهة في BASH في بضعة أسطر من الشفرة. يبدو أنه يمكن إجراء شيء ما على الأقل بسهولة عن بعد لملفات الدفعة في Windows. أنا أبحث عن حل يعمل في موجه أوامر Windows قياسي ، دون أي أدوات مساعدة إضافية. من فضلك لا PowerShell أو Cygwin سواء.


أعتقد أن إجابة E.James جيدة لأنها تعمل مع إصدارات غير معدلة من 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 (بعد أن ترجع سنوات سلبية).

ملاحظة: الرياضيات تذهب في اتجاه واحد فقط ؛ لا يمكن أن تحصل على تواريخ مستقبلية بشكل صحيح من المدخلات السلبية (ستحاول ، ولكن من المحتمل أن تتجاوز اليوم الأخير من الشهر).


أمري هو

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

@PATH - هو مجرد مسار في حالتي ، لذلك اضطررت إلى استخدام @PATH\@FILE

أيضا forfiles /? لا يعمل بالنسبة لي أيضا ، ولكن forfiles (دون "؟") عملت بشكل جيد.

والسؤال الوحيد لدي: كيفية إضافة قناع متعددة (على سبيل المثال " .log | .bak")؟

كل هذا بخصوص forfiles.exe الذي قمت بتنزيله هنا (على الفوز XP)

ولكن إذا كنت تستخدم Windows server forfiles.exe يجب أن يكون موجودًا بالفعل وأنه يختلف عن إصدار ftp. هذا هو السبب في أنني يجب أن تعديل الأمر.

بالنسبة إلى نظام التشغيل Windows Server 2003 ، أستخدم هذا الأمر:

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

إذا كان لديك مجموعة أدوات XP ، فيمكنك استخدام robocopy لنقل جميع الأدلة القديمة إلى دليل واحد ، ثم استخدم rmdir لحذف ذلك فقط:

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

استمتع:

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

راجع وثائق forfile لمزيد من التفاصيل.

لمزيد من الأشياء الجيدة ، ارجع إلى فهرس AZ من سطر أوامر Windows XP .

إذا لم يكن لديك forfiles مثبتة على جهازك ، forfiles بنسخها من أي نظام تشغيل Windows Server 2003 إلى جهاز Windows XP الخاص بك على %WinDir%\system32\ . هذا ممكن لأن EXE متوافق بشكل كامل بين Windows Server 2003 و Windows XP.

يتم تثبيت الإصدار الأحدث من Windows و Windows Server بشكل افتراضي.

لنظام التشغيل Windows 7:

لقد تغيرت الجملة قليلا. لذلك الأمر المحدث هو:

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

بالنسبة للنوافذ 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"

قد أضيف مساهمة متواضعة في هذا الموضوع القيّم بالفعل. أجد أن الحلول الأخرى قد تتخلص من نص الخطأ الفعلي ولكن تتجاهل٪ 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

باستخدام برنامج oneliner لإرجاع 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

باستخدام onliner لاحتفاظ ERRORLEVEL عند صفر للنجاح ضمن سياق batchfile في وسط التعليمات البرمجية الأخرى (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

لخطوة مهمة SQL Server عامل CmdExec هبطت على ما يلي. لا أعرف ما إذا كان خطأ ، ولكن 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%

قد تتمكن من سحب هذا الخروج. يمكنك إلقاء نظرة على هذا السؤال ، للحصول على مثال أبسط. يأتي التعقيد عندما تبدأ بمقارنة التواريخ. قد يكون من السهل معرفة ما إذا كان التاريخ أكبر أم لا ، ولكن هناك العديد من المواقف التي يجب مراعاتها إذا كنت تحتاج بالفعل إلى الحصول على الفرق بين تاريخين.

بعبارة أخرى - لا تحاول ابتكار هذا ، إلا إذا كنت لا تستطيع استخدام أدوات الطرف الثالث.


قم بنسخ هذا الرمز ثم احفظه كـ DelOldFiles.vbs.

الاستخدام فقط في COMMAND PROMPT: 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

كان بالملل من طيب قليلا وجاء مع هذا ، والذي يحتوي على نسخة بلدي من عصر لينكس لينكس رجل فقير محدودة للاستخدام اليومي (لا وقت للاحتفاظ):

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 : Change 7 for the number of days to keep.

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 يومًا. سنوات Bissextile هي جحيم لإضافة ، حقا. إذا كان لدى أحد الأشخاص فكرة لا تضيف 10 أسطر من الشفرة ، فاضغط أولاً وانشرها حتى أقوم بإضافتها إلى شفرتي.

لم أضع وقتًا في الاعتبار ، نظرًا لأن الحاجة إلى حذف الملفات أقدم من تاريخ معين ، فكانت لساعات / دقائق حذف الملفات من يوم كان من المفترض الاحتفاظ بها.

حدود

عصر يمنحها صيغة التاريخ القصير هو YYYY-MM-DD. ستحتاج إلى تعديلها من أجل إعدادات أخرى أو تقييم وقت التشغيل (قراءة sShortTime ، والتكوين المرتبط بالمستخدم ، وتكوين أمر الحقل المناسب في عامل تصفية واستخدام المرشح لاستخراج البيانات الصحيحة من الوسيطة).

هل ذكرتُ أنني أكره التنويع التلقائي لهذا المحرر؟ أنه يزيل الخطوط الفارغة ونسخ ولصق هو الجحيم.

آمل أن يساعد هذا.


ماذا عن هذا التعديل على 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

تعديل بواسطة Mofi:

تساهم الحالة أعلاه التي ساهم بها J.R. دائمًا في false نظرًا لصياغة الجملة غير الصالحة.

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

هذا ليس شيئًا مدهشًا ، لكني احتجت أن أفعل شيئًا كهذا اليوم وأديره كمهمة مجدولة إلخ.

ملف دفعي ، DelFilesOlderThanNDays.bat أدناه مع عينة 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

Expanding on aku's answer, I see a lot of people asking about UNC paths. Simply mapping the unc path to a drive letter will make forfiles happy. Mapping and unmapping of drives can be done programmatically in a batch file, for example.

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"

This will delete all files with a .gz extension that are older than 7 days. If you want to make sure Z: isn't mapped to anything else before using it you could do something simple as

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

Gosh, a lot of answers already. A simple and convenient route I found was to execute ROBOCOP.EXE twice in sequential order from a single Windows command line instruction using the & parameter.

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

In this example it works by picking all files ( . ) that are older than 30 days old and moving them to the target folder. The second command does the same again with the addition of the PURGE command which means remove files in the target folder that don't exist in the source folder. So essentially, the first command MOVES files and the second DELETES because they no longer exist in the source folder when the second command is invoked.

Consult ROBOCOPY's documentation and use the /L switch when testing.


This one did it for me. It works with a date and you can substract the wanted amount in years to go back in time:

@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

the /F in the cmd /c del @path /F forces the specific file to be deleted in some the cases the file can be read-only.

the dateYear is the year Variable and there you can change the substract to your own needs


You're probably not going to find a totally non install solution short of a complicated bat file or windows script. I use delen , drop it in a system directory then use it like the regular del command in any bat file.





cmd