سؤال

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

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

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

الحدود

عصر من المسلم به أن تنسيق التاريخ القصير الخاص بك هو YYYY-MM-DD.قد يلزم تكييفه مع الإعدادات الأخرى أو تقييم وقت التشغيل (اقرأ 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 (بدون "؟") عملت بشكل جيد.

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

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

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

بالنسبة لنظام التشغيل 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.

الاستخدام فقط في موجه الأوامر:سيسكريبت 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

استخدم الملفات.

هناك إصدارات مختلفة.تستخدم الإصدارات المبكرة معلمات نمط يونكس.

الإصدار الخاص بي (للخادم 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"

IMO، أصبحت 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

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

الشرط أعلاه ساهم به جي آر. يقيم دائما ل خطأ شنيع بسبب بناء جملة غير صالح.

و 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 بالتوقيت العالمي.ولكن يمكن أيضًا استخدام أي يوم لاحق اعتمادًا على النطاق الزمني المطلوب لدعم مهمة محددة.

جاي نشر 7daysclean.cmd يحتوي على حل سريع "التاريخ بالثواني" لمترجم سطر الأوامر cmd.exe.لكنها لا تأخذ في الاعتبار السنوات الكبيسة بشكل صحيح. جي آر. نشر اضافه لأخذ يوم كبيسة في السنة الحالية في الاعتبار، ولكن تجاهل السنوات الكبيسة الأخرى منذ سنة الأساس، أي.منذ عام 1970.

أستخدم منذ 20 عامًا الجداول الثابتة (المصفوفات) التي تم إنشاؤها مرة واحدة باستخدام وظيفة C صغيرة للحصول بسرعة على عدد الأيام بما في ذلك الأيام الكبيسة من 1970-01-01 في وظائف تحويل التاريخ/الوقت في تطبيقاتي المكتوبة بلغة C/C++.

يمكن استخدام طريقة الجدول السريعة جدًا هذه أيضًا في استخدام التعليمات البرمجية الدفعية ل يأمر.لذلك قررت ترميز الروتين الفرعي الدفعي GetSeconds الذي يحسب عدد الثواني منذ 01-01-1970 00:00:00 بالتوقيت العالمي لسلسلة التاريخ/الوقت التي تم تمريرها إلى هذا الروتين.

ملحوظة: لا يتم أخذ الثواني الكبيسة في الاعتبار نظرًا لأن أنظمة ملفات Windows لا تدعم الثواني الكبيسة أيضًا.

أولاً الجداول:

  1. الأيام منذ 01-01-1970 00:00:00 بالتوقيت العالمي المنسق لكل عام بما في ذلك الأيام الكبيسة.

    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 مع بداية الفترة 1970-01-01 ممكن فقط باستخدام متغير 32 بت غير موقّع، أي.غير موقعة طويلة (أو int غير موقعة) في C/C++.

    لكن cmd.exe استخدم للتعبيرات الرياضية متغير 32 بت موقّع.ولذلك فإن الحد الأقصى للقيمة هو 2147483647 (0x7FFFFFF) وهو 2038-01-19 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
    

يعد تحويل التاريخ إلى عدد الثواني منذ 01/01/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

للحصول على الأداء الأمثل، سيكون من الأفضل إزالة جميع التعليقات، على سبيل المثال.جميع الخطوط التي تبدأ بـ rem بعد 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

استخدام الخط الواحد لإرجاع نجاح أو فشل ERORLEVEL:

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

بالنسبة لخطوة مهمة SQL Server Agent 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%

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

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

أظن إجابة إي جيمس يعد أمرًا جيدًا نظرًا لأنه يعمل مع الإصدارات غير المعدلة من 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 أدناه مع نموذج exec مع المعلمات:

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

بالتوسع في إجابة aku، أرى الكثير من الأشخاص يسألون عن مسارات UNC.إن مجرد تعيين مسار unc إلى حرف محرك الأقراص سيجعل الملفات سعيدة.يمكن إجراء تعيين محركات الأقراص وإلغاء تعيينها برمجيًا في ملف دفعي، على سبيل المثال.

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

هذا موجود على كمبيوتر العمل بالنسبة لي وهو يعمل.أدرك أن البعض منكم قد يكون لديه حقوق أكثر تقييدًا ولكن جربها على أي حال؛) ابحث في 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