Назад | Перейти на главную страницу

Срок действия файлов в папке: удалить файлы через x дней

Я хочу создать «Папку для перетаскивания» на общем диске Windows, доступную для всех. Я бы хотел, чтобы файлы удалялись автоматически, если они находятся в папке более X дней.

Однако похоже, что все методы, которые я нашел для этого, используют дату последнего изменения, время последнего доступа или дату создания файла.

Я пытаюсь сделать это папкой, в которую пользователь может помещать файлы, чтобы поделиться с кем-нибудь. Если кто-то копирует или перемещает сюда файлы, я бы хотел, чтобы часы начали отсчитывать отсчет. Однако дата последнего изменения и дата создания файла не будут обновлены, если кто-то не изменит файл. Время последнего доступа обновляется слишком часто ... кажется, что простое открытие каталога в проводнике Windows обновит время последнего доступа.

Кто-нибудь знает решение этого? Я думаю, что ежедневная каталогизация хэшей файлов с последующим истечением срока хранения файлов на основе хэшей старше определенной даты может быть решением ... но получение хэшей файлов может занять много времени.

Благодарим за любую идею!

Примечание:
Я уже просмотрел довольно много ответов здесь ... посмотрел на монитор ресурсов файлового сервера, сценарии PowerShell, пакетные сценарии и т. Д. Они все еще используют время последнего доступа, время последнего изменения или время создания ... которое, как описано, не соответствуют вышеуказанным требованиям.

Мы использовали комбинацию сценария 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
  }
}

Если вы можете предположить NTFS, вы можете записать ключ (Guid) в альтернативный поток файла. Плюс дата, чтобы вы могли хранить базу данных в файлах.

Более подробную информацию можно найти на сайте

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

В принципе, вы можете хранить дополнительный контент в отдельном потоке, который кодируется специальным именем.

Вы можете использовать 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

Это должно быть все, что вам нужно ...

Невозможно полагаться на даты, когда файл был скопирован или перемещен в папку. Windows удается сохранить его в файловых системах, на дисках, в общих сетевых ресурсах и т. Д. Вы можете что-то решить с файловым сервером Linux или запретить людям напрямую копировать файлы с помощью FTP или веб-системы загрузки.

Если вас устраивает то, что люди не могут изменять файлы после их загрузки, у вас могут быть отдельные папки для загрузки и доступа, а также сценарий, который перемещает файлы между ними и меняет их дату. Но похоже, что вы хотите, чтобы люди могли напрямую изменять файлы.

Итак, простое, хотя и несколько хитрое решение - это испортить даты. Я бы написал два сценария:

Скрипт почасовой смены свиданий

Запустите сценарий примерно раз в час на предпочитаемом вами языке, чтобы:

  • Ищет любой файл с датой изменения за последние 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
    }
}

Запуск этого сценария сегодня (27 мая) устанавливает дату изменения всех файлов на 1 июня 1994 года - ровно 356 * 20 дней назад. Поскольку он изменяет только файлы, более новые, чем значение $ before, он не будет касаться файлов, которые уже установили в прошлое.

Сценарий очистки

Скрипт очистки будет запускаться каждую ночь и:

  • Искать файлы с датой изменения "20 лет и X дней назад"
  • Удалить их

Я не буду писать сценарий для этой части - существует множество утилит, которые могут обрабатывать удаление файлов, которые старше указанной даты, выберите то, что вам нравится. Важной частью является поиск файлов возрастом 7300+ X дней, где X - количество дней, в течение которых вы хотите их хранить с момента последнего изменения.

Преимущества

У этого есть несколько преимуществ перед другими ответами здесь:

  • Таймер сбросится, если кто-то изменит файл.
  • Нет необходимости в альтернативных потоках NTFS для маркировки файлов (которые сохраняются при перемещении файла, поэтому могут вызвать преждевременное удаление измененного файла)
  • Должен иметь минимальное влияние на производительность. Нет необходимости вести базу данных или список имён файлов и / или хешей.
  • Ничего страшного не ломается, если скрипты не запускаются. Нет необходимости в обслуживании или постоянно работающей программе для обновления даты. Всего пара запланированных задач. Решения, которые полагаются на отслеживание новых файлов и обновление времени их последнего изменения до текущего момента, могут в конечном итоге привести к удалению новых файлов, если служба выйдет из строя или перейдет в состояние гонки.

Единственная проблема, которую я вижу, заключается в том, что люди копируют файл, последний раз измененный 20 лет назад, в папку для размещения. Я думаю, что в большинстве сценариев это вряд ли будет большой проблемой, но может возникнуть.

Прошло время, но я создал относительно простой метод решения этой проблемы.

Я бы коснулся любых файлов, добавленных в каталог размещения (отслеживаемых с помощью утилиты мониторинга ресурсов), и установил бы дату последнего изменения на дату добавления в папку.

Затем я мог бы использовать дату последнего изменения, чтобы удалить все файлы, которые нужно удалить. Это также имеет то преимущество, что, если кто-то действительно обновит файл, он сбросит обратный отсчет.

Вы можете формализовать добавление файлов в раскрывающийся список через веб-страницу, на которой есть IFRAME для «загрузки». Затем пользователь может «опубликовать» файл, который вызывает задание PHP / ASP на сервере, который берет файл и помещает его в место для складывания. PHP / ASP может выполнять любое количество операций индексации / анализа.

Если кто-то копирует или перемещает сюда файлы, я бы хотел, чтобы часы начали отсчитывать отсчет. Однако дата последнего изменения и дата создания файла не будут обновлены, если кто-то фактически не изменит файл.

Я бы создал сценарий, который запускается как запланированные задачи каждые пять минут и выполняет две функции.

  1. Первым действием будет создание копии любого файла, скопированного в папку, добавление префикса к файлу и удаление оригинала. Это обеспечит единообразие даты создания файла для приложения.
  2. Второе действие будет рассматривать все файлы с предопределенным префиксом (установленным действием 1) и удалять любые из файлов с датой создания старше X дней. Это решит проблему изменения / даты доступа.

Есть уже существующий механизм для пометки файлов, бит архива. Он существует с первых дней существования DOS и присутствует как в FAT, так и в NTFS.

По сути, для каждого файла по умолчанию установлен бит архива. Если вы видите файл с участием бит архива в папке размещения, (1) очистите этот бит и (2) установите его дату на сегодняшний день. Если вы видите файл без этот бит и с датой <= 7 дней назад удалите его.

Если пользователь записывает в файл, пока он находится в папке для размещения, его бит архива устанавливается снова, поэтому его время жизни также сбрасывается до 7 дней. В конце концов, это новый файл.

Теперь вы можете безопасно использовать FileSystemWatcher. Любые проблемы (например, повторяющиеся события, потеря подробной информации из-за переполнения буфера) больше не имеют значения, поскольку вся соответствующая информация содержится в метаданных файла.