Caducar archivos en una carpeta: Eliminar archivos después de x días

12

Estoy buscando hacer una "Carpeta de colocación" en una unidad compartida de Windows que sea accesible para todos. Me gustaría que los archivos se eliminen automáticamente si permanecen en la carpeta durante más de X días.

Sin embargo, parece que todos los métodos que he encontrado para hacer esto, usan la última fecha de modificación, la última hora de acceso o la fecha de creación de un archivo.

Estoy tratando de hacer de esta una carpeta en la que un usuario pueda colocar archivos para compartir con alguien. Si alguien copia o mueve archivos aquí, me gustaría que el reloj empiece a funcionar en este punto. Sin embargo, la fecha de última modificación y la fecha de creación de un archivo no se actualizarán a menos que alguien realmente modifique el archivo. El último tiempo de acceso se actualiza con demasiada frecuencia ... parece que solo abrir un directorio en el explorador de Windows actualizará el último tiempo de acceso.

Alguien sabe de una solución a esto? Estoy pensando que catalogar el hash de archivos a diario y luego expirar archivos basados ​​en hashes anteriores a una fecha determinada podría ser una solución ... pero tomar hash de archivos puede llevar mucho tiempo.

Cualquier idea sería muy apreciada!

Nota:
Ya he visto bastantes respuestas aquí ... examiné el Monitor de recursos del servidor de archivos, los scripts de PowerShell, los scripts por lotes, etc. Todavía usan el último tiempo de acceso, el último tiempo modificado o el tiempo de creación ... que, como se describe, no se ajustan a las necesidades anteriores.

Brett G
fuente
Una pregunta, como mencionó @Michael Kjorling, ¿el temporizador deja de contar si el archivo se modifica después de dejarlo caer en la caja?
Get-HomeByFiveOClock
Lo que está buscando es el equivalente de Windows tmpwatch.
Avery Payne

Respuestas:

5

Utilizamos una combinación de un script de PowerShell y una política. La política especifica que el usuario debe crear una carpeta dentro del recurso compartido Drop_Zone y luego copiar los archivos que desee en esa carpeta. Cuando la carpeta tenga 7 días de antigüedad (usando CreationTime), el script de PowerShell la eliminará.

También agregué algunos registros al script de PowerShell para que pudiéramos verificar su funcionamiento y activé las instantáneas solo para salvar a los completamente ineptos de sí mismos.

Aquí está el script sin todas las cosas de registro.

$location = Get-ChildItem \\foo.bar\Drop_Zone
$date = Get-Date
foreach ($item in $location) {
  # Check to see if this is the readme folder
  if($item.PsIsContainer -and $item.Name -ne '_ReadMe') {
    $itemAge = ((Get-Date) - $item.CreationTime).Days
    if($itemAge -gt 7) {
      Remove-Item $item.FullName -recurse -force
    }
  }
  else {
  # must be a file
  # you can check age and delete based on that or just delete regardless
  # because they didn't follow the policy
  }
}
murisonc
fuente
1
Esto parece más simple, no se confunde con el sello de fecha y hora del archivo, las secuencias de datos alternativas o requiere alguna lista de archivos y sus fechas de caída. Iba a crear un guión increíble que hiciera todo tipo de magia, pero luego vi esto.
BeowulfNode42
y no requiere un evento de observación del sistema de archivos que active el script todo el tiempo, ya que se puede ejecutar una vez al día, y no importa mucho si se pierde un día por cualquier razón.
BeowulfNode42
2
Gran idea simple, como señaló @ BeowulfNode42. Para garantizar que los usuarios deben crear una carpeta, una simple "Denegar" de "Crear archivos / Escribir datos" ACL a "Esta carpeta solamente" asegurará que los usuarios también deben crear subcarpetas.
Brett G
3

Si puede asumir NTFS, podría escribir una clave (Guid) en una secuencia alternativa del archivo. Además de la fecha, por lo que básicamente podría almacenar la base de datos en los archivos.

Se puede encontrar más información en

http://blogs.technet.com/b/askcore/archive/2013/03/24/alternate-data-streams-in-ntfs.aspx

Básicamente, puede almacenar contenido adicional en una secuencia separada que está codificada por un nombre especial.

TomTom
fuente
¿Cómo haría uno esto?
Brett G
@BrettG Enlace agregado a la documentación. El "Flujo de datos alternativos de NTFS" lo habría hecho encontrarlo también en google, por si acaso, usted no conoce google.
TomTom
Lo siento, sé qué son las secuencias de datos alternativas, solo estaba tratando de entender su uso en este contexto. Entonces, estás diciendo que en lugar de usar un hash o algo así, usa un GUID (y / o fecha) en el flujo de datos alternativo para rastrear los archivos ... aha.
Brett G
Si. Si puede MARCAR un archivo de manera confiable, incluso puede poner la fecha de marcado en él, entonces no necesita calcular un hash.
TomTom
Solo tenga cuidado si un archivo se copia de la tienda, se edita y luego se vuelve a copiar. Desea reiniciar el temporizador, para lo cual un hash podría ser útil.
un CVn
2

Puede usar IO.FileSystemWatcher, que le permite "mirar" una carpeta para los nuevos archivos creados. Aquí están las piezas que necesitarías para que esto funcione.

Estas variables configuran la ruta para ver y un filtro para ajustar qué archivos rastrear:

$watchFolderPath = $env:USERPROFILE
$watchFolderFilter = "*.*"

Esto configura los parámetros para la carpeta a observar y las acciones a realizar cuando ocurre el evento. Básicamente, esto restablece LastWriteTime en cada archivo tal como está escrito:

$watcher = New-Object IO.FileSystemWatcher $watchFolderPath, $watchFolderFilter -Property @{
    IncludeSubdirectories = $true
    NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
    }
$onCreated = Register-ObjectEvent $watcher Created -SourceIdentifier FileCreated -Action {
    $FileName = $Event.SourceEventArgs.FullPath
    $file = Get-Item $FileName
    $file.LastWriteTime = Get-Date
    }

El evento puede ser no registrado si es necesario usando esto:

Unregister-Event -SourceIdentifier FileCreated

Finalmente, puede ejecutar esto una vez al día para limpiar los archivos antiguos:

Get-ChildItem $watchFolderPath -Recurse | Where-Object {((Get-Date)-$_.LastWriteTime).TotalDays -gt 6} | Remove-Item

Eso debería ser todo lo que necesitas ...

Tim Ferrill
fuente
Editó esto para establecer el atributo LastWriteTime cuando se crea el archivo y luego usarlo para eliminar archivos más tarde.
Tim Ferrill
1

Ha pasado un tiempo, pero configuré un método relativamente sencillo para abordar esto.

Tocaría cualquier archivo agregado al directorio desplegable (monitoreado a través de una utilidad de monitoreo de recursos) y establecería la última fecha de modificación a la fecha agregada a la carpeta.

Luego podría usar la última fecha de modificación para purgar cualquier archivo que deba ser eliminado. Esto también tiene la ventaja de que si alguien realmente actualiza el archivo, restablecerá la cuenta regresiva.

Tim Brigham
fuente
Idea perfecta Haré mi propia investigación ... pero ¿alguna idea de qué utilidad de monitoreo de recursos usaste?
Brett G
@BrettG honestamente fue hace casi 10 años. No me acuerdo Me estás haciendo sentir viejo. :) Si tuviera que hacerlo hoy, ejecutaría un trabajo basado en eventos de auditoría del sistema de archivos en el visor de eventos. El objeto FileSystemWatcher .NET está disponible a través de PowerShell, creo. Sería otra opción.
Tim Brigham
Ja, no me di cuenta de que querías decir tanto tiempo cuando dijiste "un rato". Sí, lo suficientemente divertido, solo estaba mirando FileSystemWatcher. Aunque, no creo que funcione con archivos movidos / copiados. ¡Gracias por la respuesta!
Brett G
1
@BrettG - Filesystemwatcher podría usarse junto con una tabla de seguimiento, pero tiene sus propios problemas. Ver aquí: stackoverflow.com/questions/1764809/… stackoverflow.com/questions/6000856/filesystemwatcher-issues
JohnP
1
@BrettG - Además, esta es una buena extensión para FSW: codeproject.com/Articles/58740/…
JohnP
1

No hay forma de confiar en las fechas para cuando un archivo fue copiado o movido a una carpeta. Windows logra preservarlo en sistemas de archivos, unidades, recursos compartidos de red, etc. Es posible que pueda resolver algo con un servidor de archivos de Linux, o evitar que las personas copien directamente archivos mediante FTP o un sistema de carga basado en la web.

Si está de acuerdo con que las personas no puedan modificar los archivos después de que se carguen, podría tener carpetas de carga y acceso separadas, y un script que mueva los archivos entre ellas y las vuelva a actualizar. Pero parece que quiere que las personas puedan modificar los archivos directamente.

Por lo tanto, una solución simple, aunque un tanto extravagante, sería meterse con las fechas. Escribiría dos guiones:

Script de cambio de fecha por hora

Haga que se ejecute una secuencia de comandos una vez cada hora, en su idioma preferido, que:

  • Busca cualquier archivo con una fecha modificada en los últimos 20 años.
  • Cuando encuentre dicho archivo, cambie su fecha de modificación a hoy menos 20 años.

En powershell, se vería así:

$path = "D:\test"

$today = Get-Date
$before = $today.AddDays(-7300) #356*20 days

Get-ChildItem -Recurse -Path $path | foreach {
    if ($_.LastWriteTime -gt $before) {
        Write-Host $_.Name
        $_.LastWriteTime = $before
    }
}

Al ejecutar este script hoy (27 de mayo), se establece la fecha de modificación de todos los archivos al 1 de junio de 1994, exactamente hace 356 * 20 días. Debido a que está cambiando solo los archivos más nuevos que el valor $ before, no tocará los archivos que ya ha establecido en el pasado.

Script de limpieza

El script de limpieza se ejecutaría todas las noches y:

  • Buscar archivos con fecha de modificación "hace 20 años y X días"
  • Borra los

No escribiré el script para esta parte: hay muchas utilidades que pueden manejar la eliminación de archivos que son anteriores a una fecha específica, elija la que desee. La parte importante es buscar archivos que tengan más de 7300 días de antigüedad, donde X es el número de días que desea conservarlos desde la última modificación.

Ventajas

Esto tiene algunas ventajas sobre las otras respuestas aquí:

  • El temporizador se reiniciará si alguien modifica el archivo.
  • No es necesario que las secuencias alternativas de NTFS marquen los archivos (que se conservan al mover el archivo, por lo que podrían causar la eliminación prematura de un archivo modificado)
  • Debería tener un impacto mínimo en el rendimiento. No es necesario mantener una base de datos o una lista de nombres de archivo y / o hashes.
  • Nada se rompe horriblemente si los scripts no se ejecutan. No se necesita ningún servicio o programa en ejecución constante para actualizar la fecha. Solo un par de tareas programadas. Las soluciones que dependen de buscar nuevos archivos y actualizar su última hora de modificación en este momento podrían terminar eliminando nuevos archivos si el servicio falla o se encuentra en una condición de carrera.

El único problema que puedo ver es si las personas copian un archivo que se modificó por última vez hace 20 años en la carpeta desplegable. Creo que en la mayoría de los escenarios, es poco probable que sea un gran problema, pero podría surgir.

Conceder
fuente
0

Puede formalizar la adición de archivos al cuadro desplegable a través de una página web, que tiene un IFRAME de "carga". Luego, el usuario podría "publicar" el archivo, que invoca un trabajo PHP / ASP en el servidor, que toma el archivo y lo coloca en la ubicación del disco. El PHP / ASP podría realizar cualquier cantidad de operaciones de índice / análisis.

Simon Catlin
fuente
0

Si alguien copia o mueve archivos aquí, me gustaría que el reloj empiece a funcionar en este punto. Sin embargo, la fecha de última modificación y la fecha de creación de un archivo no se actualizarán a menos que alguien realmente modifique el archivo.

Crearía un script que se ejecuta como tareas programadas cada cinco minutos y hace dos cosas.

  1. La primera acción sería hacer una copia de cualquier archivo copiado en la carpeta, colocar un prefijo en el archivo y eliminar el original. Esto garantizaría que la fecha de creación del archivo fuera uniforme para la aplicación.
  2. La segunda acción vería todos los archivos con el prefijo predeterminado (establecido con la acción 1) y eliminaría cualquiera de los que tengan una fecha de creación anterior a X días. Esto resolvería el problema de modificación / fecha de acceso.
usuario1914368
fuente
0

Hay un mecanismo existente para marcar archivos, el bit de archivo. Ha estado allí desde los primeros días de DOS, y está presente tanto en FAT como en NTFS.

Básicamente, cada archivo tendrá su bit de archivo configurado de forma predeterminada. Si ve un archivo con el bit de archivo en su carpeta de colocación, (1) borre ese bit y (2) establezca su fecha hoy. Si ve un archivo sin ese bit y con una fecha <= 7 días en el pasado, elimínelo.

Si un usuario escribe en el archivo mientras está en la carpeta de colocación, su bit de archivo se establece de nuevo para que su vida útil también se restablezca a 7 días. Es en efecto un nuevo archivo, después de todo.

Ahora puede usar FileSystemWatcher de forma segura. Cualquier problema que tenga (como eventos duplicados, desbordamiento del búfer que pierde información detallada) ya no importa, ya que la información relevante está en los metadatos del archivo.

MSalters
fuente