fecha - script para borrar temporales de windows
Archivo por lotes para borrar archivos anteriores a N días (23)
Estoy buscando una manera de eliminar todos los archivos de más de 7 días en un archivo por lotes. He buscado en la web y he encontrado algunos ejemplos con cientos de líneas de código y otros que requieren la instalación de utilidades de línea de comandos adicionales para realizar la tarea.
Se pueden hacer cosas similares en BASH en solo un par de líneas de código. Parece que algo al menos remotamente fácil podría hacerse para archivos por lotes en Windows. Estoy buscando una solución que funcione en un símbolo de sistema estándar de Windows, sin ninguna utilidad adicional. Por favor, no PowerShell o Cygwin tampoco.
¿Puedo agregar una humilde contribución a este ya valioso hilo? Estoy encontrando que otras soluciones podrían eliminar el texto de error real pero están ignorando el% ERRORLEVEL% que indica un error en mi aplicación. Y legítimamente quiero% ERRORLEVEL% siempre que no sea el error "No se encontraron archivos".
Algunos ejemplos:
Depuración y eliminación del error específicamente:
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
Usando un oneliner para devolver el éxito o el fracaso de 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
Usar un oneliner para mantener el ERRORLEVEL en cero para tener éxito dentro del contexto de un archivo por lotes en medio de otro código (ver> nul restablece el 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
Para un paso de trabajo de CmdExec del Agente SQL Server caí en lo siguiente. No sé si es un error, pero el CmdExec dentro del paso solo reconoce la primera línea de código:
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%
¿Qué tal esta modificación en 7daysclean.cmd para tomar en cuenta un año bisiesto?
¡Se puede hacer en menos de 10 líneas de codificación!
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
Editado por Mofi:
La condición anterior contribuida por J.R. evalúa siempre como falsa debido a una sintaxis no válida.
Y el Month GEQ 2
también está equivocado porque agregar 86400 segundos por un día más debe hacerse en un año bisiesto solo para los meses de marzo a diciembre, pero no para febrero.
Un código de trabajo para tener en cuenta el día bisiesto, solo en el año en curso, en el archivo por lotes 7daysclean.cmd publicado por sería:
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
Ampliando la respuesta de aku, veo a mucha gente preguntando sobre los caminos de UNC.Simplemente mapear la ruta unc a una letra de unidad hará felices a los archivos. La asignación y desasignación de unidades se pueden realizar mediante programación en un archivo por lotes, por ejemplo.
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"
Esto eliminará todos los archivos con una extensión .gz que tengan más de 7 días. Si desea asegurarse de que Z: no esté asignado a otra cosa antes de usarlo, podría hacer algo simple como
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!"
)
Copie este código y guárdelo como DelOldFiles.vbs.
USO ÚNICO EN EL PEDIDO DEL COMANDO: cscript DelOldFiles.vbs 15
15 significa borrar archivos con más de 15 días de antigüedad.
''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
Creo que la respuesta de e.James es buena, ya que funciona con versiones no modificadas de Windows tan pronto como Windows 2000 SP4 (y posiblemente antes), pero requería escribir en un archivo externo. Aquí hay una versión modificada que no crea un archivo de texto externo mientras mantiene la compatibilidad:
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)
Para ser fiel a la pregunta original, aquí está en un guión que hace TODA la matemática si lo llama con el número de días como parámetro:
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)
NOTA: El código anterior toma en cuenta los años bisiestos, así como el número exacto de días en cada mes. El único máximo es el número total de días que ha habido desde 0/0/0 (después de eso devuelve años negativos).
NOTA: Las matemáticas solo van de una manera; no puede obtener correctamente las fechas futuras de la entrada negativa (lo intentará, pero es probable que pase el último día del mes).
Disfrutar:
forfiles -p "C:/what/ever" -s -m *.* -d <number of days> -c "cmd /c del @path"
Consulte la documentación de forfile para más detalles.
Para obtener más información, consulte Un índice AZ de la línea de comandos de Windows XP .
Si no tiene forfiles
instalados en su máquina, cópielo desde cualquier Windows Server 2003 a su máquina con Windows XP en %WinDir%/system32/
. Esto es posible ya que el EXE es totalmente compatible entre Windows Server 2003 y Windows XP.
Las versiones posteriores de Windows y Windows Server lo tienen instalado de forma predeterminada.
Para Windows 7:
La sintaxis ha cambiado un poco. Por lo tanto el comando actualizado es:
forfiles /p "C:/what/ever" /s /m *.* /D -<number of days> /C "cmd /c del @path"
Eche un vistazo a mi answer a una pregunta similar :
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"
Esto elimina los archivos anteriores a una fecha determinada. Estoy seguro de que se puede modificar para regresar siete días después de la fecha actual.
actualización: observo que HerbCSO ha mejorado en el script anterior. Recomiendo usar su versión en su lugar.
Ejecuta los siguientes commands :
ROBOCOPY C:/source C:/destination /mov /minage:7
del C:/destination /q
Mueva todos los archivos (usando / mov, que mueve los archivos y luego los borra en lugar de / move que mueve todos los filetrees que luego se eliminan) a través de robocopy a otra ubicación, y luego ejecute un comando de eliminación en esa ruta y ya está bueno.
Además, si tiene un directorio con muchos datos, puede usar el conmutador /mir
En mi opinión, JavaScript se está convirtiendo gradualmente en un estándar de scripting universal: probablemente esté disponible en más productos que cualquier otro lenguaje de scripting (en Windows, está disponible mediante Windows Scripting Host). Tengo que limpiar los archivos viejos en muchas carpetas, así que aquí hay una función de JavaScript para hacer eso:
// 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);
}
}
Para que se borre cada carpeta, solo agregue otra llamada a la función clearFolder (). Este código en particular también preserva los archivos exe y dll, y limpia las subcarpetas también.
Mi comando es
forfiles -p "d:/logs" -s -m*.log -d-15 -c"cmd /c del @PATH/@FILE"
@PATH
- es solo una ruta en mi caso, así que tuve que usar @PATH/@FILE
tambien para forfiles /?
no funciona para mí también, pero para forfiles
(sin "?") funcionó bien.
Y la única pregunta que tengo: ¿cómo agregar una máscara múltiple (por ejemplo, " .log | .bak")?
Todo esto relacionado con forfiles.exe que descargué aquí (en Windows XP)
Pero si está utilizando Windows Server forfiles.exe ya debería estar allí y es diferente de la versión ftp. Es por eso que debo modificar el comando.
Para Windows Server 2003 estoy usando este comando:
forfiles -p "d:/Backup" -s -m *.log -d -15 -c "cmd /c del @PATH"
Muy a menudo hay preguntas relativas a la fecha / hora relativas para resolver con el archivo por lotes. Pero el intérprete de línea de comandos cmd.exe no tiene ninguna función para los cálculos de fecha / hora. Ya se han publicado muchas buenas soluciones de trabajo con aplicaciones de consola o scripts adicionales aquí, en otras páginas de y en otros sitios web.
Común para las operaciones basadas en la fecha / hora es el requisito para convertir una cadena de fecha / hora en segundos desde un día determinado. Muy común es 1970-01-01 00:00:00 UTC. Sin embargo, cualquier día posterior también se puede utilizar según el intervalo de fechas requerido para dar soporte a una tarea específica.
publicó 7daysclean.cmd contiene una solución rápida de "fecha a segundos" para el intérprete de línea de comandos cmd.exe . Pero no toma en cuenta correctamente los años bisiestos. J.R. publicó un add-on para tomar en cuenta el día bisiesto del año en curso, pero ignorando los otros años bisiestos desde el año base, es decir, desde 1970.
Uso desde hace 20 años tablas estáticas (arrays) creadas una vez con una pequeña función C para obtener rápidamente el número de días, incluidos los días bisiestos desde 1970-01-01 en las funciones de conversión de fecha / hora en mis aplicaciones escritas en C / C ++.
Este método de tabla muy rápido se puede usar también en código de lote usando el comando FOR . Así que decidí codificar la subrutina de lote GetSeconds
que calcula el número de segundos desde 1970-01-01 00:00:00 UTC para una cadena de fecha / hora pasada a esta rutina.
Nota: Los segundos de salto no se tienen en cuenta, ya que los sistemas de archivos de Windows tampoco admiten los segundos de salto.
Primero, las tablas:
Días desde 1970-01-01 00:00:00 UTC para cada año, incluidos los días bisiestos.
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
Calcular los segundos para los años 2039 a 2106 con la época que comienza 1970-01-01 solo es posible utilizando una variable de 32 bits sin signo, es decir, sin signo largo (o sin signo int) en C / C ++.
Pero cmd.exe utiliza para expresiones matemáticas una variable de 32 bits con signo. Por lo tanto, el valor máximo es 2147483647 (0x7FFFFFFF) que es 2038-01-19 03:14:07.
Información de año bisiesto (No / Sí) para los años 1970 a 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
Número de días al primer día de cada mes en el año en curso.
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
La conversión de una fecha a la cantidad de segundos desde 1970-01-01 es bastante fácil usando esas tablas.
¡Atención por favor!
El formato de las cadenas de fecha y hora depende de la configuración regional y de idioma de Windows. Los delimitadores y el orden de los tokens asignados a las variables de entorno Day
, Month
y Year
en el primer ciclo FOR de GetSeconds
deben adaptarse al formato de fecha / hora local si es necesario.
Es necesario adaptar la cadena de fecha de la variable de entorno si el formato de fecha en la variable de entorno DATE es diferente al formato de fecha utilizado por el comando FOR en %%~tF
.
Por ejemplo, cuando %DATE%
expande a Sun 02/08/2015
mientras que %%~tF
expande a 02/08/2015 07:38 PM
el siguiente código se puede usar con la modificación de la línea 4 para:
call :GetSeconds "%DATE:~4% %TIME%"
Esto resulta en pasar a la subrutina solo 02/08/2015
- la cadena de fecha sin las 3 letras de la abreviatura del día de la semana y el carácter de espacio de separación.
Alternativamente, los siguientes podrían usarse para pasar la fecha actual en el formato correcto:
call :GetSeconds "%DATE:~-10% %TIME%"
Ahora, los últimos 10 caracteres de la cadena de fecha se pasan a la función GetSeconds
y, por lo tanto, no importa si la cadena de fecha de la variable de entorno DATE es o no entre semana, siempre que el día y el mes estén siempre con 2 dígitos en el orden esperado, es decir, en formato dd/mm/yyyy
o dd.mm.yyyy
.
Aquí está el código de lote con comentarios explicativos que solo muestran qué archivo eliminar y qué archivo mantener en el árbol de carpetas C:/Temp
, vea el código del primer ciclo 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
Para un rendimiento óptimo, sería mejor eliminar todos los comentarios, es decir, todas las líneas que comienzan con rem después de 0-4 espacios iniciales.
Y las matrices también se pueden hacer más pequeñas, es decir, disminuyendo el rango de tiempo de 1980-01-01 00:00:00 a 2038-01-19 03:14:07 como lo admite actualmente el código de lote anterior, por ejemplo, a 2015-01 -01 a 2019-12-31 ya que el código de abajo utiliza lo que realmente elimina los archivos con más de 7 días en el árbol de carpetas C:/Temp
.
Además, el código de lote siguiente está optimizado para el formato de 24 horas.
@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
Para obtener aún más información sobre los formatos de fecha y hora y las comparaciones de tiempo de archivos en Windows, consulte mi respuesta en Averigüe si el archivo tiene más de 4 horas en archivos por lotes con mucha información adicional sobre los tiempos de los archivos.
Ok se aburrió un poco y se me ocurrió esto, que contiene mi versión del reemplazo de la época de Linux de un hombre pobre limitada para el uso diario (sin retención de tiempo):
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
USO
set /a strip=day*7
: Cambia 7 por el número de días a mantener.
set dSource=C:/temp
: Este es el directorio de inicio para verificar archivos.
NOTAS
Este es un código no destructivo, mostrará lo que habría sucedido.
Cambio :
if !epoch! LEQ %slice% (echo DELETE %%f ^(%%~tf^)) ELSE echo keep %%f ^(%%~tf^)
a algo como:
if !epoch! LEQ %slice% del /f %%f
así que los archivos realmente se borran
Febrero : está codificado a 28 días. Los años bissextiles es un infierno para agregar, de verdad. Si alguien tiene una idea que no agregaría 10 líneas de código, continúe y publique, así que la agrego a mi código.
época : no tomé el tiempo en consideración, ya que la necesidad es eliminar los archivos anteriores a una fecha determinada, tomar horas / minutos habría eliminado los archivos de un día destinado a su conservación.
LIMITACIÓN
La época da por sentado que su formato de fecha corta es YYYY-MM-DD. Tendría que adaptarse para otras configuraciones o para una evaluación en tiempo de ejecución (lea sShortTime, la configuración vinculada al usuario, configure el orden de campo adecuado en un filtro y use el filtro para extraer los datos correctos del argumento).
¿Mencioné que odio el autoformado de este editor? elimina las líneas en blanco y copiar y pegar es un infierno.
Espero que esto ayude.
Para Windows 2012 R2 funcionaría lo siguiente:
forfiles /p "c:/FOLDERpath" /d -30 /c "cmd /c del @path"
para ver los archivos que serán borrados usa este
forfiles /p "c:/FOLDERpath" /d -30 /c "cmd /c echo @path @fdate"
Para Windows Server 2008 R2:
forfiles /P c:/sql_backups/ /S /M *.sql /D -90 /C "cmd /c del @PATH"
Esto eliminará todos los archivos .sql que tengan más de 90 días.
Si tiene el kit de recursos de XP, puede usar robocopy para mover todos los directorios antiguos a un solo directorio, luego use rmdir para eliminar solo ese:
mkdir c:/temp/OldDirectoriesGoHere
robocopy c:/logs/SoManyDirectoriesToDelete/ c:/temp/OldDirectoriesGoHere/ /move /minage:7
rmdir /s /q c:/temp/OldDirectoriesGoHere
Usted podría ser capaz de lograr esto. Puedes echar un vistazo a esta pregunta , para un ejemplo más simple. La complejidad viene, cuando empiezas a comparar las fechas. Puede ser fácil saber si la fecha es mayor o no, pero hay muchas situaciones a considerar si necesita obtener la diferencia entre dos fechas.
En otras palabras, no intente inventar esto, a menos que realmente no pueda usar las herramientas de terceros.
Utilice forfiles.
Hay diferentes versiones. Los primeros utilizan parámetros de estilo Unix.
Mi versión (para el servidor 2000 - no tenga espacio después de los conmutadores) -
forfiles -p"C:/what/ever" -s -m*.* -d<number of days> -c"cmd /c del @path"
Para agregar archivos a XP, obtenga el archivo exe de ftp://ftp.microsoft.com/ResKit/y2kfix/x86/
y agregarlo a C: / WINDOWS / system32
esto no es nada sorprendente, pero necesitaba hacer algo como esto hoy y ejecutarlo como tarea programada, etc.
archivo por lotes, DelFilesOlderThanNDays.bat a continuación con el ejemplo de ejecución con parámetros:
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
ROBOCOPY funciona muy bien para mí. Originalmente sugerí mi Iman. Pero en lugar de mover los archivos / carpetas a un directorio temporal y luego eliminar el contenido de la carpeta temporal, mueva los archivos a la papelera.
Estas son algunas líneas de mi archivo por lotes de copia de seguridad, por ejemplo:
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
Limpia cualquier cosa que tenga más de 15 días de mi carpeta ''Temp'' y 30 días para cualquier cosa en mi carpeta de copia de seguridad de AutoCAD. Uso variables porque la línea puede ser bastante larga y puedo reutilizarla para otras ubicaciones. Solo necesita encontrar la ruta de acceso a la papelera de reciclaje asociada con su inicio de sesión.
Esto está en una computadora de trabajo para mí y funciona. Entiendo que algunos de ustedes pueden tener derechos más restrictivos, pero inténtelo de todos modos;) Busque explicaciones en Google sobre los parámetros de ROBOCOPY
¡Aclamaciones!
Mi script para borrar archivos anteriores a un año específico:
@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
Éste lo hizo por mí. Funciona con una fecha y puede restar la cantidad deseada en años para retroceder en el tiempo:
@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
el /F
de las cmd /c del @path /F
fuerzas del archivo específico que desea eliminar en algunos casos el archivo puede ser de sólo lectura.
el dateYear
es la variable año y no se puede cambiar el restar a sus propias necesidades
Gosh, muchas respuestas ya. Una ruta simple y conveniente que encontré fue ejecutar ROBOCOP.EXE dos veces en orden secuencial desde una única instrucción de línea de comandos de Windows usando el parámetro & .
ROBOCOPY.EXE SOURCE-DIR TARGET-DIR *.* /MOV /MINAGE:30 & ROBOCOPY.EXE SOURCE-DIR TARGET-DIR *.* /MOV /MINAGE:30 /PURGE
En este ejemplo, funciona seleccionando todos los archivos ( . ) Que tienen más de 30 días de antigüedad y moviéndolos a la carpeta de destino. El segundo comando vuelve a hacer lo mismo con la adición del comando PURGAR, que significa eliminar los archivos de la carpeta de destino que no existen en la carpeta de origen. Esencialmente, el primer comando MUEVE los archivos y el segundo SUPRIME porque ya no existen en la carpeta de origen cuando se invoca el segundo comando.
Consulte la documentación de ROBOCOPY y use el interruptor / L al realizar la prueba.
forfiles /p "v:" /s /m *.* /d -3 /c "cmd /c del @path"
Debes hacer /d -3
(3 días antes) Esto funciona bien para mí. Así que todos los lotes complicados podrían estar en la papelera. Además, forfiles
no admite rutas UNC, por lo tanto, realice una conexión de red a un disco específico.