ログファイルを一杯作るので、消してくれという依頼があった。
ただし、このフォルダには、上記のログを作るファイルがいくつかああって
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ユーザーです。
ログの一定期間の自動消去は私もよく使います。フリーのいいものがないので自作しましたが、コンポーネントになっていて組み込みになっていると使いやすいですよね。スケジューラーで自動起動して定期的に消去できると最高です。
コメントを投稿