動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2018/01/09)
ファイル名に日付が入っている状況で、指定日付以前のファイルを削除する処理。
対象ファイル
bash > Brace Expansionで日付のダミーファイルを作る | ファイル名失敗時: MinGW32でファイルを消す
にて作ったファイル。
v0.1, v0.2
code
Unit1.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <IOUtils.hpp>
#include <memory>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
/*
v0.2 2017/10/17
- リストの対象ファイルを削除 (ゴミ箱には行かない)
- isDateBefore()追加
- getFileDateTime()追加
v0.1 2017/10/17
- 対象フォルダにあるファイルリストを取得
*/
String kTargetFolder = L"D:\\WORK\\filedelete_171017";
TDateTime kLastDate = VarToDateTime("2017/01/15 00:00:00"); // Note: VarToDateTime()使用時はLマクロにしない
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
static TDateTime getFileDate(String filePath)
{
String filename = ExtractFileName(filePath);
// filename:
// 例:"X_20170131.csv" (2017 Jan. 31のファイル)
String strdt = filename.SubString(3, 8); // 3: yyyyの開始インデックス
// 12345678
// yyyymmdd
strdt.Insert("/", 7); // mmとddの間
strdt.Insert("/", 5); // yyyyとmmの間
OutputDebugString(filename.c_str());
return VarToDateTime(strdt + L" 00:00:00");
}
static bool isDateBefore(String filepath, TDate lastDate)
{
TDateTime trgt;
try {
trgt = getFileDate(filepath);
} catch (...) {
return false; // ファイル名が日付型でない場合
}
if (trgt > lastDate) {
return false;
}
return true;
}
void __fastcall TForm1::dbgB_getListClick(TObject *Sender)
{
String searchPattern = L"*.csv";
TSearchOption option = TSearchOption::soAllDirectories;
TStringDynArray fileList = TDirectory::GetFiles(kTargetFolder, searchPattern, option);
int allcnt = fileList.Length;
std::unique_ptr<TStringList> lst(new TStringList);
TDateTime filedt;
for(int idx = 0; idx < fileList.Length; idx++) {
if (isDateBefore(fileList[idx], kLastDate) == false) {
continue;
}
lst->Add(fileList[idx]);
TFile::Delete(fileList[idx]); /***********************/
}
String msg = IntToStr(lst->Count) + L"/" + IntToStr(allcnt);
OutputDebugString(msg.c_str());
Memo1->Lines->Assign(lst.get());
}
//---------------------------------------------------------------------------
実行結果
2017/01/15
までのファイルが削除される。
備考
TFile::Delete()の場合、ごみ箱に行かずに削除される
(Shift + Deleteと同じ)。
TFile::Move()でごみ箱に移動しようかと検討したが、ごみ箱のパスを取得する方法が見つかっていない。
関連: https://qiita.com/7of9/items/7bb5d9837c696754995d
v0.3
- 最終日だけでなく、最終日と日数に変更
- 処理を関数化
Unit1.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <IOUtils.hpp>
#include <DateUtils.hpp>
#include <memory>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
/*
v0.3 2017/10/17
- change to range
+ isInRange() takes [days] arg
+ refactor > rename isDateBefore() to isInRange()
- deletePastFiles()追加
v0.2 2017/10/17
- リストの対象ファイルを削除 (ゴミ箱には行かない)
- isDateBefore()追加
- getFileDateTime()追加
v0.1 2017/10/17
- 対象フォルダにあるファイルリストを取得
*/
String kTargetFolder = L"D:\\WORK\\filedelete_171017";
TDateTime kLastDate = VarToDateTime("2017/01/15 00:00:00"); // Note: VarToDateTime()使用時はLマクロにしない
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
static TDateTime getFileDate(String filePath)
{
String filename = ExtractFileName(filePath);
// filename:
// 例:"X_20170131.csv" (2017 Jan. 31のファイル)
String strdt = filename.SubString(3, 8); // 3: yyyyの開始インデックス
// 12345678
// yyyymmdd
strdt.Insert("/", 7); // mmとddの間
strdt.Insert("/", 5); // yyyyとmmの間
OutputDebugString(filename.c_str());
return VarToDateTime(strdt + L" 00:00:00");
}
static bool isInRange(String filepath, TDate lastDate, int days)
{
TDateTime trgt;
TDateTime startdt = IncDay(lastDate, -(days - 1));
try {
trgt = getFileDate(filepath);
} catch (...) {
return false; // ファイル名が日付型でない場合
}
if (trgt < startdt) {
return false;
}
if (trgt > lastDate) {
return false;
}
return true;
}
void __fastcall TForm1::deletePastFiles(String filePattern, TDateTime lastDate, int days, String targetDir, TStringList *delList)
{
TSearchOption option = TSearchOption::soAllDirectories;
TStringDynArray fileList = TDirectory::GetFiles(kTargetFolder, filePattern, option);
int allcnt = fileList.Length;
for(int idx = 0; idx < fileList.Length; idx++) {
if (isInRange(fileList[idx], lastDate, days) == false) {
continue;
}
if (delList != NULL) {
delList->Add(fileList[idx]);
}
TFile::Delete(fileList[idx]); // ごみ箱に行かずに消える
}
}
void __fastcall TForm1::dbgB_getListClick(TObject *Sender)
{
int days = 10; // テスト用
std::unique_ptr<TStringList> lst(new TStringList);
deletePastFiles(L"*.csv", kLastDate, /*days=*/days, /*targetDir=*/kTargetFolder, lst.get());
Memo1->Lines->Assign(lst.get());
String msg = IntToStr(lst->Count) + L" deleted";
OutputDebugString(msg.c_str());
}
//---------------------------------------------------------------------------
1月6日から1月15日のファイルを消すようになった。