使文件夹中的文件过期:x天后删除文件


12

我正在寻找一个Windows共享驱动器中的“拖放文件夹”,每个人都可以使用。如果文件在文件夹中放置超过X天,我希望将其自动删除。

但是,似乎所有找到的方法都可以使用该文件的最后修改日期,最后访问时间或创建日期。

我试图将其设置为一个文件夹,用户可以在其中放置文件以与他人共享。如果有人将文件复制或移动到此处,我希望时钟从现在开始计时。但是,除非有人实际修改了文件,否则文件的最后修改日期和创建日期将不会更新。上次访问时间更新太频繁了……似乎只是在Windows资源管理器中打开目录会更新上次访问时间。

有人知道解决方案吗?我认为每天对文件的哈希进行分类,然后根据早于某个特定日期的哈希值使文件过期可能是一种解决方案....但是获取文件哈希值可能会很耗时。

任何想法将不胜感激!

注意:
在这里,我已经看了很多答案...研究了文件服务器资源监视器,powershell脚本,批处理脚本等。它们仍然使用上次访问时间,上次修改时间或创建时间...如上所述,这不符合上述需求。


@Michael Kjorling提到的一个问题是,如果将文件放入框中后对其进行了修改,计时器是否会停止计数?
Get-HomeByFiveOClock

您要寻找的是Windows的Windows版本tmpwatch
艾利·佩恩

Answers:


5

我们结合使用了Powershell脚本和策略。该策略指定用户必须在Drop_Zone共享内​​创建一个文件夹,然后将所需的任何文件复制到该文件夹​​中。当文件夹的使用期限达到7天时(使用CreationTime),powershell脚本将其删除。

我还向powershell脚本添加了一些日志记录,以便我们可以验证它的操作并打开卷影副本,只是为了保存完全无效的内容。

这是没有所有日志记录内容的脚本。

$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
  }
}

1
这似乎是最简单的,不需要弄乱文件日期时间戳,备用数据流,也不需要文件列表及其删除日期。我打算创建一个很棒的脚本,可以完成各种魔术,但是后来我看到了。
BeowulfNode42 2014年

并且不需要文件系统监视事件始终触发脚本,因为它可以每天运行一次,并且无论出于何种原因而错过一天都没关系。
BeowulfNode42 2014年

2
非常简单的主意,就像@ BeowulfNode42指出的那样。为了确保用户必须创建文件夹,将“创建文件/写入数据” ACL的简单“拒绝” ACL设置为“仅此文件夹”将确保用户也必须创建子文件夹。
Brett G

3

如果可以假定使用NTFS,则可以将密钥(Guid)写入文件的备用流中。加上日期,因此您基本上可以将数据库存储在文件中。

可以在以下位置找到更多信息

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

基本上,您可以将其他内容存储在由特殊名称编码的单独流中。


一个人怎么做?
Brett G

@BrettG添加了指向文档的链接。“ NTFS备用数据流”会让您也在google中找到它,以防万一-您不知道google。
TomTom

抱歉,我知道什么是备用数据流,我只是想了解它们在这种情况下的用法。因此,您是说在替代数据流中使用GUID(和/或日期)来跟踪文件,而不是使用哈希或其他内容。
Brett G

是的 如果您可以可靠地标记文件-您甚至可以在文件中添加标记日期-那么就不需要计算哈希值。
TomTom 2014年

只要注意文件是否已从存储中复制,编辑然后再复制回去即可。然后,您想重新启动计时器,对此可能有用的是散列。
2014年

2

您可以使用IO.FileSystemWatcher,它允许您“监视”文件夹中创建的新文件。这是完成这项工作所需的部分。

这些变量配置要监视的路径和筛选器以微调要跟踪的文件:

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

这将设置要监视的文件夹的参数以及事件发生时要执行的操作。基本上,这会在写入每个文件时重置LastWriteTime:

$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
    }

如果需要,可以使用以下方法注销该事件:

Unregister-Event -SourceIdentifier FileCreated

最后,您可以每天运行一次以清理旧文件:

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

那应该是您需要的一切...


编辑此文件以在创建文件时设置LastWriteTime属性,然后使用该属性稍后删除文件。
蒂姆·费里尔

1

已经有一段时间了,但是我建立了一个相对简单的方法来解决这个问题。

我将触摸添加到放置目录的任何文件(通过资源监视实用程序进行监视),并将最后修改日期设置为添加到文件夹的日期。

然后,我可以使用上次修改的日期来清除所有需要老化的文件。这还有一个优势,如果有人确实更新了文件,它将重置倒数计时。


完美的主意。我将自己进行研究。.但是知道您使用了哪种资源监视实用程序?
Brett G

老实说,@ BrettG已经快十年了。我不记得了 你让我觉得老。:)如果今天要这样做,我将在事件查看器中根据文件系统审核事件执行一项工作。我认为可以通过PowerShell使用FileSystemWatcher .NET对象。这将是另一种选择。
蒂姆·布里格姆

哈,当你说“一会儿”时,我没意识到你的意思那么久。是的,很有趣,我只是在看FileSystemWatcher。虽然,我认为它不适用于移动/复制的文件。谢谢回复!
Brett G

1
@BrettG-Filesystemwatcher可以与跟踪表一起使用,但是它有其自身的问题。在这里看到:stackoverflow.com/questions/1764809/... stackoverflow.com/questions/6000856/filesystemwatcher-issues
JohnP

1
@BrettG -而且,这是一个很好的扩展FSW:codeproject.com/Articles/58740/...
JohnP

1

没有办法依赖文件复制或移动到文件夹中的日期。Windows设法在文件系统,驱动器,网络共享等中保留它。您可以使用linux文件服务器来解决问题,或者阻止人们使用FTP或基于Web的上传系统直接复制文件。

如果您认为人们上传后无法修改文件,可以设置单独的上传和访问文件夹,并使用脚本在文件之间移动并重新命名。但这听起来像您希望人们能够直接修改文件。

因此,一个简单的解决方案(如果有些棘手)将弄乱日期。我会写两个脚本:

每小时更改日期脚本

以您喜欢的语言每小时运行一次左右的脚本,该脚本是:

  • 查找最近20年内修改日期的任何文件。
  • 找到此类文件后,请将其修改日期更改为今天减去20年。

在powershell中,它看起来像这样:

$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
    }
}

今天(5月27日)运行此脚本,将所有文件的修改日期设置为1994年6月1日-恰好是356 * 20天前。因为它仅更改比$ before值新的文件,所以它不会触摸已设置为过去的文件。

清理脚本

清理脚本将每天晚上运行,并且:

  • 搜索日期修改为“ 20年X天前”的文件
  • 删除它们

我不会为这部分编写脚本-有很多实用程序可以处理删除指定日期之前的文件,请选择任意一个。重要的部分是查找7300 + X天前的文件,其中X是自上次修改以来您要保留的天数。

优点

与此处的其他答案相比,它具有一些优点:

  • 如果有人修改文件,计时器将重置。
  • 无需NTFS替代流来标记文件(在移动文件时保留这些流,因此可能会导致过早删除已修改的文件)
  • 如果有任何性能影响,则应具有最小限度。无需保留数据库或文件名和/或哈希列表。
  • 如果脚本无法运行,一切都不会令人震惊。不需要服务或不断运行的程序来更新日期。只是几个预定的任务。如果服务失败或进入竞争状态,则依赖监视新文件并立即将其最近修改时间更新为现在的解决方案可能最终会删除新文件。

我能看到的唯一问题是人们是否将20年前最后修改的文件复制到放置文件夹。我认为在大多数情况下,这不太可能成为一个大问题,但它可能会出现。


0

您可以通过一个具有“上载” IFRAME的网页来正式将文件添加到该放置箱中。然后,用户可以“发布”该文件,从而在服务器上调用PHP / ASP作业,该作业将获取文件并将其放置在皱褶位置。PHP / ASP可以执行任何数量的索引/分析操作。


0

如果有人将文件复制或移动到此处,我希望时钟从现在开始计时。但是,除非有人实际修改了文件,否则文件的最后修改日期和创建日期将不会更新。

我将创建一个脚本,该脚本每五分钟作为计划任务运行一次,并执行两项操作。

  1. 第一个动作是将复制到该文件夹​​中的所有文件复制一份,在文件上加上前缀,然后删除原始文件。这样可以确保文件的创建日期与应用程序一致。
  2. 第二个动作将查看具有预定前缀(用动作1设置)的所有文件,并删除任何创建日期早于X天的文件。这样可以解决修改/访问日期的问题。

0

有一种标记文件的机制,即存档位。自DOS早期以来,它就一直存在,并且同时存在于FAT和NTFS上。

基本上,每个文件都会默认设置其存档位。如果您在放置文件夹中看到带有存档位的文件,则(1)清除该位,然后(2)将日期设置为今天。如果您看到的文件没有该位,并且日期小于7天,则将其删除。

如果用户在文件放在放置文件夹中时对其进行写操作,则会再次设置其存档位,因此其生存期也将重置为7天。毕竟,它实际上是一个新文件。

现在,您可以安全地使用FileSystemWatcher。它具有的任何问题(例如重复事件,缓冲区溢出会丢失详细信息)都不再重要,因为相关信息都在文件元数据中。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.