ログファイルを一杯作るので、消してくれという依頼があった。
ただし、このフォルダには、上記のログを作るファイルがいくつかああって
3世代程度は残してくれという依頼があった。
昔、仕事で触ってたOpenVmsのファイルシステムにはバージョンというのが
あって、古いバージョンのファイルを消すPurgeコマンドがあり
これとにたようなものが欲しいなということで、とりあえず作ってみた。
(本家には似ても似つかぬ、あくまでももどきですが。)
使い方は、
PurgeMock "パージファイルマスク" /D:パージファイルがあるフォルダ /G:残す世代数
で、/R: を指定することで、パージファイルマスクに正規表現が使用できます。
また、ファイルの更新日時を基準に/G:で指定した数だけ残るよう古い日付のものを
削除しますが、 /T:を指定することでファイルの作成日時を基準にPurgeすることが
できます。
なお、パージファイルマスクにより、複数の異なるファイル名のファイルが削除対象
となりえますが、このツールでは、このような場合のことを想定しておりません。
(/G:で指定した数になるようにばっさり消します。)
以下、ソース(delphi Xeがあればコンパイル可能です。)を置いておきます。
ライセンスは、MITライセンスとします。
ソース使用は自由ですが、無保証とします。
まずはメイン。
program PurgeMock; {$APPTYPE CONSOLE} uses SysUtils, PurgeMockImp in 'PurgeMockImp.pas', MidasLib ; function CreatePurgeMockParams : TPurgeMockParams; var PurgeMockParams : TPurgeMockParams; i : Integer; begin PurgeMockParams := TPurgeMockParams.Create; try try PurgeMockParams.Init(Paramstr(0)); for i := 1 to ParamCount -1 do begin PurgeMockParams.SetPurgeParam(Paramstr(i)); end; except PurgeMockParams.Free; PurgeMockParams := nil; end; finally Result := PurgeMockParams; end; end; var PurgeMockParams : TPurgeMockParams; DoPurgeMock : TPuregMock; Ret : Integer; begin try { TODO -oUser -cConsole メイン : ここにコードを記述してください } PurgeMockParams := CreatePurgeMockParams; if Assigned(PurgeMockParams) then begin DoPurgeMock := TPuregMock.Create(PurgeMockParams); try Ret := DoPurgeMock.Purge; finally DoPurgeMock.Free; end; PurgeMockParams.Free; end; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end.
次に、パージコマンドの本体
unit PurgeMockImp; interface uses SysUtils ,DB ,DBClient ; type TPurgeTimeStamp = (ptCreate, ptUpdate); TPurgeMockParams = class private FTargetDir: String; FUseRegularExpression: Boolean; FFileMask: String; FLeavingGenerations: Integer; FPurgeTimeStamp: TPurgeTimeStamp; procedure SetTargetDir(val: String); procedure SetUseRegularExpression(val: Boolean); procedure SetFileMask(val: String); procedure SetLeavingGenerations(val: Integer); procedure SetPurgeTimeStamp(val: TPurgeTimeStamp); public property TargetDir: String read FTargetDir write SetTargetDir; property UseRegularExpression: Boolean read FUseRegularExpression write SetUseRegularExpression; property FileMask: String read FFileMask write SetFileMask; property LeavingGenerations: Integer read FLeavingGenerations write SetLeavingGenerations; property PurgeTimeStamp: TPurgeTimeStamp read FPurgeTimeStamp write SetPurgeTimeStamp; procedure Init(ExePath: String); procedure SetPurgeParam(PurgeParam : String); end; TPuregMock = class public constructor Create(Params: TPurgeMockParams); function Purge: Integer; destructor Destroy; override; strict private FPurgeMockParams: TPurgeMockParams; FPurgeMockDataSet : TClientDataSet; function MakePurgeFileList: Integer; function ExecPurge: Integer; function CreatePurgeDataSet : TClientDataSet; end; function TryParseCmdLineSw(ParameterString : String; Sw : Array of String; var ParamValue : String; IgnoreCase: Boolean = true) : boolean; implementation Uses StrUtils ,IOUtils ,Types ,RegularExpressionsCore ; procedure TPurgeMockParams.SetTargetDir(val: String); begin FTargetDir := val; end; procedure TPurgeMockParams.SetUseRegularExpression(val: Boolean); begin FUseRegularExpression := val; end; procedure TPurgeMockParams.Init(ExePath: String); begin FTargetDir := ExtractFileDir(ExePath); FUseRegularExpression := false; FileMask := '*.*'; FLeavingGenerations := 1; FPurgeTimeStamp := ptUpdate; end; procedure TPurgeMockParams.SetFileMask(val: String); begin FFileMask := val end; procedure TPurgeMockParams.SetLeavingGenerations(val: Integer); begin if Val >= 0 then begin FLeavingGenerations := val; end else begin FLeavingGenerations := 0; end; end; procedure TPurgeMockParams.SetPurgeParam(PurgeParam: String); var ValueStr : String; begin if TryParseCmdLineSw(PurgeParam,['/D:','-D:'],ValueStr) then begin FTargetDir := ValueStr; Exit; end; if TryParseCmdLineSw(PurgeParam,['/U:','-U:'],ValueStr) then begin FUseRegularExpression := true; Exit; end; if TryParseCmdLineSw(PurgeParam,['/G:','-G:'],ValueStr) then begin LeavingGenerations := StrToIntDef(ValueStr,1); Exit; end; if TryParseCmdLineSw(PurgeParam,['/T:','-T:'],ValueStr) then begin FPurgeTimeStamp := ptCreate; Exit; end; if TryParseCmdLineSw(PurgeParam,[],ValueStr) then begin FFileMask := ValueStr; Exit; end; end; procedure TPurgeMockParams.SetPurgeTimeStamp(val: TPurgeTimeStamp); begin FPurgeTimeStamp := val; end; constructor TPuregMock.Create(Params: TPurgeMockParams); begin inherited Create; FPurgeMockParams := Params; end; function TPuregMock.Purge: Integer; begin Result := -1; FPurgeMockDataSet := CreatePurgeDataSet; if Assigned(FPurgeMockDataSet) then begin if MakePurgeFileList > 0 then begin Result := ExecPurge; end; FPurgeMockDataSet.EmptyDataSet; FPurgeMockDataSet.Active := false; FPurgeMockDataSet.Free; end; end; function TPuregMock.CreatePurgeDataSet: TClientDataSet; var PurgeDataSet : TClientDataSet; FD : TFieldDef; begin PurgeDataSet := TClientDataSet.Create(nil); try try FD := PurgeDataSet.FieldDefs.AddFieldDef; FD.Name := 'FileName'; FD.DataType := ftString; FD.Size := 1024; FD := PurgeDataSet.FieldDefs.AddFieldDef; FD.Name := 'TimeStamp'; FD.DataType := ftDatetime; PurgeDataSet.CreateDataSet; PurgeDataSet.AddIndex('Purge_Idx','TimeStamp;FileName',[]); PurgeDataSet.IndexName := 'Purge_Idx'; Except if Assigned(PurgeDataSet) then PurgeDataSet.Free; PurgeDataSet := nil; end; finally Result := PurgeDataSet; end; end; destructor TPuregMock.Destroy; begin if Assigned(FPurgeMockParams) then begin FPurgeMockParams := nil; end; inherited Destroy; end; function TPuregMock.MakePurgeFileList: Integer; var SearchOption: TSearchOption; SearchDir : TDirectory; SearchFileMask : String; LList: TStringDynArray; FileFullName,FileName : String; CanAddList : Boolean; PerlRegEx: TPerlRegEx; PurgeFile : TFile; begin Result := 0; //使っても使わなくても正規表現用のクラスをオープンしておく。 PerlRegEx:= TPerlRegEx.Create; try SearchOption := TSearchOption.soTopDirectoryOnly; SearchFileMask := FPurgeMockParams.FileMask; if FPurgeMockParams.UseRegularExpression then begin PerlRegEx.RegEx := SearchFileMask; SearchFileMask := '*.*'; end; try LList := SearchDir.GetFiles(FPurgeMockParams.FTargetDir,SearchFileMask, SearchOption); FPurgeMockDataSet.Active := true; for FileFullName in LList do begin CanAddList := true; if FPurgeMockParams.UseRegularExpression then begin FileName := ExtractFileName(FileFullName); PerlRegEx.Subject := FileName; CanAddList := PerlRegEx.Match; end; if CanAddList then begin //パージ対象リストに追加 FPurgeMockDataSet.Append; FPurgeMockDataSet.FieldByName('FileName').AsString := FileFullName; if FPurgeMockParams.FPurgeTimeStamp = ptCreate then begin FPurgeMockDataSet.FieldByName('TimeStamp').AsDateTime := PurgeFile.GetCreationTime(FileFullName); end else begin FPurgeMockDataSet.FieldByName('TimeStamp').AsDateTime := PurgeFile.GetLastAccessTime(FileFullName); end; FPurgeMockDataSet.Post; end; end; Result := FPurgeMockDataSet.RecordCount; except Result := -1; end; finally if Assigned(PerlRegEx) then PerlRegEx.Free; end; end; function TPuregMock.ExecPurge: Integer; var DeleteCount : integer; DeleteFileName : string; PurgeFile : TFile; begin DeleteCount := 0; try FPurgeMockDataSet.Active := true; FPurgeMockDataSet.First; while not(FPurgeMockDataSet.Eof) do begin DeleteFileName := FPurgeMockDataSet.FieldByName('FileName').AsString; PurgeFile.Delete(DeleteFileName); inc(DeleteCount); //レコードをDeleteした場合は、Next不要なので注意 FPurgeMockDataSet.Delete; if FPurgeMockDataSet.RecordCount <= FPurgeMockParams.LeavingGenerations then Break; end; Result := DeleteCount; Except Result := -1; end; end; function TryParseCmdLineSw(ParameterString : String; Sw : Array of String; var ParamValue : String; IgnoreCase: Boolean) : boolean; var i : integer; begin Result := false; if Length(Sw) = 0 then begin //SW指定がない場合はそのままの文字列を返す ParamValue := ParameterString; Result := true; end else begin for i := low(Sw) to high(Sw) do begin if IgnoreCase then begin if StartsText(Sw[i],ParameterString) then begin Result := true; ParamValue := ReplaceText(ParameterString,Sw[i],''); Break; end; end else begin if StartsStr(Sw[i],ParameterString) then begin Result := true; ParamValue := ReplaceStr(ParameterString,Sw[i],''); Break; end; end; end; end; end; end.
1 件のコメント:
こんにちは、通りすがりのDelphiユーザーです。
ログの一定期間の自動消去は私もよく使います。フリーのいいものがないので自作しましたが、コンポーネントになっていて組み込みになっていると使いやすいですよね。スケジューラーで自動起動して定期的に消去できると最高です。
コメントを投稿