web-dev-qa-db-ja.com

フォルダー内のファイルを期限切れにする:x日後にファイルを削除する

誰でもアクセスできるWindows共有ドライブに「ドロップフォルダー」を作成したいと考えています。ファイルがX日間を超えてフォルダに残っている場合は、ファイルが自動的に削除されるようにしてください。

ただし、これを行うには、ファイルの最終変更日、最終アクセス時間、または作成日を使用するすべての方法を使用しているようです。

これを、ユーザーがファイルをドロップして誰かと共有できるフォルダーにしようとしています。誰かがファイルをここにコピーまたは移動した場合、この時点で時計がカチカチと音を立て始めます。ただし、誰かが実際にファイルを変更しない限り、ファイルの最終更新日と作成日は更新されません。最終アクセス時刻が頻繁に更新されています... Windowsエクスプローラーでディレクトリを開くだけで、最終アクセス時刻が更新されるようです。

これに対する解決策を知っている人はいますか?ファイルのハッシュを毎日カタログ化し、特定の日付よりも古いハッシュに基づいてファイルを期限切れにすることが解決策になるかもしれないと考えています。しかし、ファイルのハッシュを取得することは時間がかかる可能性があります。

どんなアイデアでも大歓迎です!

注:
私はここでかなり多くの回答を見てきました...ファイルサーバーリソースモニター、powershellスクリプト、バッチスクリプトなどを調べました。彼らはまだ最終アクセス時刻、最終変更時刻、または作成時刻を使用しています...説明したように、上記のニーズに適合しません。

12
Brett G

PowerShellスクリプトとポリシーを組み合わせて使用​​しました。このポリシーでは、ユーザーがDrop_Zone共有内にフォルダーを作成し、必要なファイルをそのフォルダーにコピーする必要があることを指定しています。フォルダーが(CreationTimeを使用して)7日経過すると、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
  }
}
5
murisonc

NTFSを想定できる場合は、ファイルの代替ストリームにキー(Guid)を書き込むことができます。加えて日付なので、基本的にはデータベースをファイルに保存できます。

詳細については、

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

基本的に、特別な名前でコード化された別のストリームに追加のコンテンツを保存できます。

3
TomTom

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

最後に、古いファイルをクリーンアップするために、これを1日に1回実行できます。

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

それはあなたが必要とするすべてであるべきです...

2
Tim Ferrill

久しぶりですが、これに対処するための比較的単純な方法を設定しました。

ドロップディレクトリ(リソース監視ユーティリティで監視)に追加されたファイルを変更し、最終更新日をフォルダーに追加された日付に設定します。

次に、最終更新日を使用して、期限切れにする必要のあるファイルをすべて削除できます。これには、誰かが実際にファイルを更新した場合にカウントダウンがリセットされるという利点もあります。

1
Tim Brigham

ファイルがコピーまたはフォルダーに移動された日付に依存する方法はありません。 Windowsは、ファイルシステム、ドライブ、ネットワーク共有などでファイルを保持するように管理しています。Linuxファイルサーバーを使用して問題を解決したり、FTPまたはWebベースのアップロードシステムを使用してファイルを直接コピーしたりできないようにすることができます。

アップロード後にファイルを変更できない場合は、アップロードフォルダーとアクセスフォルダーを個別に用意し、ファイルをフォルダー間で移動して更新するスクリプトを使用できます。しかし、人々がファイルを直接変更できるようにしたいようです。

したがって、単純な、多少ハックな場合の解決策は、日付を台無しにすることです。 2つのスクリプトを記述します。

時間ごとの日付変更スクリプト

スクリプトを1時間に1回程度、希望する言語で実行します。

  • 過去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年前に最後に変更されたファイルをドロップフォルダーにコピーしたかどうかです。ほとんどのシナリオでは、それが大きな問題になる可能性は低いと思いますが、それが発生する可能性があります。

1
Grant

ファイルをマークするための既存のメカニズム、アーカイブビットがあります。それはDOSの初期の頃から存在し、FATとNTFSの両方に存在しています。

基本的に、すべてのファイルにはデフォルトでアーカイブビットが設定されています。ファイルが表示された場合withドロップフォルダーのアーカイブビット、(1)そのビットをクリアし、(2)日付を今日に設定します。ファイルなしそのビットがあり、過去7日以下の日付がある場合は、それを削除します。

ドロップフォルダー内にあるユーザーがファイルに書き込むと、アーカイブビットが再度設定されるため、ファイルの有効期間も7日間にリセットされます。結局のところ、これは実際には新しいファイルです。

これで、FileSystemWatcherを安全に使用できます。関連情報がすべてファイルメタデータに含まれているため、問題の重複(イベントの重複、バッファオーバーフローによる詳細情報の喪失など)は問題ではなくなりました。

0
MSalters

誰かがファイルをここにコピーまたは移動した場合、この時点で時計がカチカチと音を立て始めます。ただし、ファイルの最終変更日と作成日は、誰かが実際にファイルを変更しない限り更新されません。

5分ごとにスケジュールされたタスクとして実行され、2つのことを行うスクリプトを作成します。

  1. 最初のアクションでは、フォルダーにコピーされたファイルのコピーを作成し、ファイルにプレフィックスを付けて、元のファイルを削除します。これにより、アプリケーションのファイルの作成日が統一されます。
  2. 2番目のアクションは、事前定義されたプレフィックス(アクション1で設定)を持つすべてのファイルを調べ、作成日がX日より古いファイルをすべて削除します。これにより、変更/アクセスされた日付の問題が解決されます。
0
user1914368

「アップロード」IFRAMEがあるWebページを介して、ドロップボックスへのファイルの追加を形式化できます。次に、ユーザーはファイルを「ポスト」し、サーバー上でPHP/ASPジョブを呼び出して、ファイルを取得し、それをpuckerの場所に配置します。 PHP/ASPは、任意の数のインデックス/分析操作を実行できます。

0
Simon Catlin