문제

배치 파일에서 7일이 지난 모든 파일을 삭제하는 방법을 찾고 있습니다.저는 웹을 검색하여 수백 줄의 코드가 포함된 몇 가지 예와 작업을 수행하기 위해 추가 명령줄 유틸리티를 설치해야 하는 다른 예를 찾았습니다.

비슷한 일이 있을 수 있다 BASH에서 완료 단 몇 줄의 코드로.Windows에서 배치 파일에 대해 최소한 원격으로 쉬운 작업을 수행할 수 있는 것 같습니다.저는 추가 유틸리티 없이 표준 Windows 명령 프롬프트에서 작동하는 솔루션을 찾고 있습니다.PowerShell이나 Cygwin도 사용하지 마세요.

도움이 되었습니까?

해결책

즐기다:

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

보다 파일 문서화 상세 사항은.

더 많은 사은품을 참고하세요 Windows XP 명령줄의 A-Z 색인.

당신이 가지고 있지 않다면 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

robocopy를 통해 모든 파일을 다른 위치로 이동한 다음(전체 파일 트리를 이동한 다음 삭제하는 /move와 반대로 파일을 이동한 다음 삭제하는 /mov 사용) 다음 해당 경로에서 삭제 명령을 실행하면 모두 완료됩니다. 좋은.

또한 많은 데이터가 포함된 디렉토리가 있는 경우 다음을 사용할 수 있습니다. /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

그래서 파일이 실제로 삭제됩니다

2월: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"

특정 날짜보다 오래된 파일을 삭제합니다.현재 날짜로부터 7일 전으로 돌아가도록 수정될 수 있다고 확신합니다.

업데이트: HerbCSO가 위 스크립트에서 개선되었음을 확인했습니다.나는 사용하는 것이 좋습니다 그의 버전 대신에.

내 명령은

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

@PATH - 내 경우에는 경로일 뿐이므로 사용해야 했습니다. @PATH\@FILE

또한 forfiles /? 나한테도 일하진 않지만 forfiles ("?" 없이) 잘 작동했습니다.

그리고 내가 가진 유일한 질문은 다음과 같습니다.여러 마스크를 추가하는 방법(예: ".log|.박")?

forfiles.exe에 관한 모든 것 여기에서 다운로드했습니다 (승리 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

forfile을 사용하세요.

다양한 버전이 있습니다.초기 버전에서는 유닉스 스타일 매개변수를 사용했습니다.

내 버전(서버 2000의 경우 - 스위치 뒤에 공백이 없음을 참고하세요)-

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

XP에 forfile을 추가하려면 다음에서 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 스크립팅 호스트를 사용하여 사용할 수 있음).많은 폴더에서 오래된 파일을 정리해야 하므로 이를 수행하는 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의 편집:

위의 조건은 다음에 의해 기여되었습니다. J.R. 항상 평가한다 거짓 잘못된 구문 때문입니다.

그리고 Month GEQ 2 하루를 더 86400초 더하는 것은 3월부터 12월까지의 달에 대해서만 윤년에 이루어져야 하고 2월에는 그렇지 않기 때문에 잘못된 것입니다.

윤일을 고려하는 작업 코드 - 현재 연도에만 - 배치 파일에서 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.그러나 정확한 윤년은 고려되지 않습니다. J.R. 게시한 부가 기능 현재 연도의 윤일은 고려하지만 기준 연도 이후의 다른 윤년은 무시합니다.1970년부터.

저는 20년 동안 C/C++로 작성된 애플리케이션의 날짜/시간 변환 함수에서 1970-01-01의 윤일을 포함한 일수를 빠르게 얻기 위해 작은 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
    

    1970-01-01을 시작으로 2039년부터 2106년까지의 초 계산은 부호 없는 32비트 변수를 사용하는 경우에만 가능합니다.C/C++의 unsigned long(또는 unsigned int)입니다.

    하지만 cmd.exe 수학적 표현에는 부호 있는 32비트 변수를 사용합니다.따라서 최대값은 2147483647(0x7FFFFFFF), 즉 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. 현재 연도의 매월 1일까지의 일수입니다.

                       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
    

해당 테이블을 사용하면 1970-01-01 이후 날짜를 초 수로 변환하는 것이 매우 쉽습니다.

주의해주세요!

날짜 및 시간 문자열의 형식은 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 - 요일 약어 3자와 구분 공백 문자가 없는 날짜 문자열입니다.

또는 다음을 사용하여 현재 날짜를 올바른 형식으로 전달할 수 있습니다.

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

이제 날짜 문자열의 마지막 10자가 함수에 전달됩니다. GetSeconds 따라서 환경 변수의 날짜 문자열은 중요하지 않습니다. 날짜 일과 월이 항상 예상 순서대로 2자리 숫자인 한 평일이 있든 없든 상관없습니다. 즉,형식으로 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

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

다른 코드 중간에 배치 파일 컨텍스트 내에서 성공을 위해 oneliner를 사용하여 ERRORLEVEL을 0으로 유지합니다(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%

XP 리소스 키트가 있는 경우 robocopy를 사용하여 모든 이전 디렉터리를 단일 디렉터리로 이동한 다음 rmdir을 사용하여 해당 디렉터리만 삭제할 수 있습니다.

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

제 생각에는 e.James의 답변 Windows 2000 SP4(또는 그 이전 버전)만큼 수정되지 않은 Windows 버전에서 작동하므로 좋지만 외부 파일에 써야 했습니다.호환성을 유지하면서 외부 텍스트 파일을 생성하지 않는 수정된 버전은 다음과 같습니다.

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 이후의 총 일수입니다(그 이후에는 음수 연도를 반환합니다).

메모:수학은 한 방향으로만 진행됩니다.음수 입력에서 미래 날짜를 올바르게 가져올 수 없습니다(시도는 하겠지만 해당 월의 마지막 날이 지나갈 가능성이 높습니다).

이것을 풀 수 있을 수도 있습니다.당신은 살펴볼 수 있습니다 이 질문, 더 간단한 예를 들어 보겠습니다.날짜를 비교하기 시작하면 복잡해집니다.날짜가 더 큰지 아닌지 쉽게 알 수 있지만 실제로 두 날짜 간의 차이를 구해야 하는 경우 고려해야 할 상황이 많습니다.

즉, 실제로 제3자 도구를 사용할 수 없는 경우가 아니라면 이를 고안하려고 하지 마십시오.

이것은 놀라운 일이 아니지만 오늘 이와 같은 작업을 수행하고 예약된 작업 등으로 실행해야 했습니다.

배치 파일(아래의 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

aku의 답변을 확장하면 많은 사람들이 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"

이렇게 하면 7일보다 오래된 .gz 확장자를 가진 모든 파일이 삭제됩니다.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!"
)

이런, 이미 많은 답변이 있습니다.내가 찾은 간단하고 편리한 경로는 다음을 사용하여 단일 Windows 명령줄 명령에서 ROBOCOPY.EXE를 순차적으로 두 번 실행하는 것이었습니다. & 매개변수.

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

'Temp' 폴더에서 15일 이상 지난 항목을 정리하고, AutoCAD 백업 폴더에 있는 항목 중 30일 이상 지난 항목을 정리합니다.줄이 꽤 길어지고 다른 위치에서 재사용할 수 있기 때문에 변수를 사용합니다.로그인과 관련된 휴지통에 대한 dos 경로를 찾으면 됩니다.

이것은 업무용 컴퓨터에 있으며 작동합니다.귀하 중 일부는 더 제한적인 권리를 갖고 있을 수 있지만 어쨌든 시도해 보십시오.) ROBOCOPY 매개변수에 대한 설명을 Google에서 검색하세요.

건배!

이것은 나를 위해 해냈습니다.날짜와 함께 작동하며 시간을 거슬러 올라가기 위해 원하는 연도 금액을 뺄 수 있습니다.

@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