[windows] N 일보다 오래된 파일을 삭제하는 배치 파일

배치 파일에서 7 일보다 오래된 모든 파일을 삭제하는 방법을 찾고 있습니다. 웹을 검색 한 결과 수백 줄의 코드가 포함 된 예제와 작업을 수행하기 위해 추가 명령 줄 유틸리티를 설치해야하는 예제가 있습니다.

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



답변

즐겨:

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

자세한 내용은 forfiles설명서 를 참조하십시오.

자세한 내용 은 Windows XP 명령 줄의 AZ 색인을 참조하십시오 .

forfiles컴퓨터에 설치 하지 않은 경우 Windows Server 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를 통해 모든 파일을 이동하고 (/ mov를 사용하여 파일을 이동 한 다음 전체 파일 트리를 이동 한 다음 삭제되는 / move와 반대로 삭제) 파일을 다른 위치로 이동 한 다음 해당 경로에서 삭제 명령을 실행하면 좋은.

또한 데이터가 많은 디렉토리가 있으면 /mir스위치 를 사용할 수 있습니다


답변

Ok는 조금 지루했고 이것에 대해 생각해 냈습니다. 여기에는 매일 사용하도록 제한된 가난한 사람의 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 일 전) 이것은 나를 위해 잘 작동합니다. 따라서 모든 복잡한 배치는 휴지통에있을 수 있습니다. 또한 forfilesUNC 경로를 지원하지 않으므로 특정 드라이브에 네트워크로 연결하십시오.


답변

비슷한 질문에 대한대답 을 살펴보십시오 .

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 | .bak”)?

여기 에서 다운로드 한 forfiles.exe에 관한 모든 (XP에서 승리)

그러나 Windows 서버를 사용하는 경우 forfiles.exe가 이미 있어야하며 ftp 버전과 다릅니다. 그렇기 때문에 명령을 수정해야합니다.

Windows Server 2003의 경우 다음 명령을 사용하고 있습니다.

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


답변

배치 파일로 해결해야 할 상대 날짜 / 시간 관련 질문이 매우 많습니다. 그러나 명령 줄 인터프리터 cmd.exe 에는 날짜 / 시간 계산 기능이 없습니다. 추가 콘솔 응용 프로그램 또는 스크립트를 사용하는 많은 훌륭한 작업 솔루션이 이미 여기, 스택 오버플로의 다른 페이지 및 다른 웹 사이트에 게시되어 있습니다.

날짜 / 시간을 기준으로하는 작업에는 일반적으로 날짜 / 시간 문자열을 결정된 날짜 이후 초로 변환해야합니다. 1970-01-01 00:00:00 UTC가 매우 일반적입니다. 그러나 특정 작업을 지원하는 데 필요한 날짜 범위에 따라 나중에 사용할 수도 있습니다.

Jay 는 명령 줄 인터프리터 cmd.exe에 대한 빠른 “날짜-초”솔루션이 포함 된 7daysclean.cmd 를 게시 했습니다 . 그러나 올바른 윤년을 고려하지는 않습니다. JR 은 현재 연도의 도약 일을 고려 하여 추가 기능을 게시 했지만 기본 연도 이후, 즉 1970 년 이후의 다른 도약은 무시합니다.

나는 C / C ++로 작성된 응용 프로그램의 날짜 / 시간 변환 함수에서 1970-01-01의 윤일을 포함하여 일 수를 빠르게 얻기 위해 작은 C 함수로 한 번 만든 20 년 이후 정적 테이블 (배열)을 사용합니다.

이 매우 빠른 테이블 방법은 FOR 명령을 사용하는 배치 코드에서도 사용할 수 있습니다 . 그래서이 루틴에 GetSeconds전달 된 날짜 / 시간 문자열에 대해 1970-01-01 00:00:00 UTC 이후의 초 수를 계산 하는 배치 서브 루틴을 코딩하기로 결정했습니다 .

참고 : Windows 파일 시스템은 윤초를 지원하지 않으므로 윤초는 고려되지 않습니다.

먼저, 테이블 :

  1. 1970 년 1 월 1 일 이후 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로 시작하는 에포크 (epoch)를 사용하여 2039 년에서 2106 년까지의 초를 계산하는 것은 부호없는 32 비트 변수, 즉 C / C ++에서 부호없는 long (또는 부호없는 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. 현재 연도의 매월 첫 날부터 시작하는 일 수입니다.

                       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, MonthYear제에서 FOR의 루프 GetSeconds필요한 경우 로컬 날짜 / 시간 형식에 적합해야한다.

환경 변수 DATE의 날짜 형식이 FOR on 명령 에 의해 사용 된 날짜 형식과 다른 경우 환경 변수의 날짜 문자열을 조정해야합니다 %%~tF.

예를 들어 아래 코드로 %DATE%확장하는 Sun 02/08/2015동안 %%~tF확장하면 02/08/2015 07:38 PM4 행을 다음과 같이 수정하여 사용할 수 있습니다.

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

결과적으로 02/08/20153 개의 요일 약어와 공백 문자가없는 날짜 문자열 인 서브 루틴으로 전달됩니다 .

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

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

이제 날짜 문자열의 마지막 10자가 함수로 전달 GetSeconds되므로 환경 변수 DATE 의 날짜 문자열에 요일이 있거나없는 요일이 있거나없는 경우 형식 dd/mm/yyyy 또는 형식으로 항상 예상되는 순서로 2 자리 숫자를 갖는 한 중요하지 않습니다 dd.mm.yyyy.

다음은 삭제하려는 파일과 C:\Temp폴더 트리 에 보관할 파일을 출력하는 주석을 설명하는 배치 코드입니다 . 첫 번째 FOR 루프의 코드를 참조하십시오 .

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

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

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


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

:GetSeconds

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

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

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

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

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

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

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

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

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

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

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

rem Exit this subroutine
goto :EOF

최적의 성능을 위해서는 모든 주석, 즉 0-4 선행 공백 후 rem으로 시작하는 모든 행을 제거하는 것이 가장 좋습니다 .

또한 배열을 더 작게 만들 수 있습니다. 즉, 위의 배치 코드에서 현재 지원하는대로 시간 범위를 1980-01-01 00:00:00에서 2038-01-19 03:14:07로 줄입니다 (예 : 2015-01). 아래 코드에서 -01 ~ 2019-12-31은 C:\Temp폴더 트리 에서 7 일이 지난 파일을 실제로 삭제합니다 .

또한 아래의 배치 코드는 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 시간보다 오래된 지 찾기대한 답변을 참조하십시오 .