Delphi удалить файлы по маске
Проблема:
Есть каталог с файлами измерений ( *.csv ) и другими файлами.
Каждые несколько часов будет создаваться новый файл измерений.
Мне нужна возможность удалить все файлы .csv в этой папке, которые старше определенного количества дней. Все остальные типы файлов трогать не следует.
Вопрос:
Есть ли в Delphi встроенная функция для выполнения этой работы? Если нет, то каков эффективный способ решения этой проблемы?
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно.
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей.
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то.
Ответы 2
Я не нашел встроенной функции Delphi для этой конкретной проблемы.
Эта функция работала для меня:
Это метод «старой школы». Я предполагаю, что решение с использованием System.IOUtils и TDirectory тоже сработает.
По крайней мере, этот подход позволяет избежать всего выделения кучи IOUtils, исторически использовавшегося с ошибками модуля fwiw.
Я бы сказал, что FindClose номинально неуместен - он должен следовать за оператором if iFindResult = 0 (иначе FindClose не будет выполнен, если FindFirst вернет 0) и что if iFindResult = 0 является избыточным, поскольку while позаботится о случае, когда FindFirst возвращает 0.
@Magoo Функция findclose закрывает успешный поиск файлов FindFirst (и FindNext). Это освобождает ресурсы, используемые поиском в SearchResults. Вызов findclose необязателен, если FindFirst ничего не находит, но должен вызываться, если находит, даже если последующий вызов FindNext завершается ошибкой.
@MichaelHutter Конечно. Вот почему я сказал «номинально» — на том основании, что выполнение и выполнение действия должно быть сбалансированным, а не условным (слишком много проблем, вызванных дисбалансом). конкретно указывает FindFirst allocates resources (memory) that must be released by calling FindClose , но пример кода нарушает это направление. . Изучение кода показывает, что findClose автоматически выполняется FindFirst для ненулевого возврата.
Почему плохо выполнять это в одной процедуре? Ваш подход включает в себя два отдельных перечисления, которые мне кажутся плохой идеей.
Я прочитал ОП, так как должны быть выполнены оба требования (соответствовать маске И быть старше нескольких дней), поэтому вы не можете разделить поиск на две процедуры, вам нужно проверить оба условия в одной и той же процедуре.
Да, оба требования должны быть выполнены, что и делается. Значение по умолчанию для DaysOld и связанный с ним комментарий в ответе OP создают впечатление, что у процедуры есть дополнительное намерение - удаление файлов по маске. По сути, удаление файлов с помощью чего-то вроде DeleteFilesOlderThanXDays('C:\') делает код неясным. Кто-то еще, читающий код, может не понять смысла: он предназначен для удаления всех файлов (что тогда с именем подпрограммы?), или вы просто забыли указать параметр? Это может потребовать дополнительного ввода, но явный код лучше, чем неявный.
Мне необходимо удалить все файлы по заданной маске (*.zzz) на копмьютере. Если сделать поиск по FindFirst. то работает слишком долго.
Может мне ShFileOperation сможет помочь ?
FillChar(fromBuf, SizeOf(fromBuf), 0);
FillChar(fromBuf, SizeOf(toBuf), 0);
StrPCopy(fromBuf, "c:\*.zzz");
with OpStruct do
begin
wnd:=Handle;
wFunc:=FO_DELETE;
pFrom:=@fromBuf;
pTo:=@toBuf;
fFlags:=FOF_NOCONFIRMATION or
FOF_NOERRORUI or
FOF_SILENT;
fAnyOperationsAborted:=false;
hNameMappings:=Nil;
lpszProgressTitle:=Nil;
end;
ShFileOperation(OpStruct);
Удаляет только файлы только в корне диска, а хотелось бы чтобы удалялось и во всех поддиректориях.
"Если сделать поиск по FindFirst. то работает слишком долго."
Интересуют другие варианты.
← →KoluChi ( 2002-11-21 17:46 ) [4]
>"Если сделать поиск по FindFirst. то работает слишком долго."
А ты видел где-нибудь мнгновенный поиск?
Поиск в Windows быстрый?
KoluChi ( 2002-11-21 17:50 ) [5]
IMHO, ShFileOperation в поиске не поможет :(
← →ЮРИЙ_К ( 2002-11-21 17:51 ) [6]
Дык чего голову ломать, в RX есть специальнно для этого функция
← →sers ( 2002-11-21 17:54 ) [7]
>> Дык чего голову ломать, в RX есть специальнно для этого функция
Не подскажешь какая ?
← →KoluChi ( 2002-11-21 17:59 ) [8]
RX: FileUtil.pas
function DeleteFiles(const FileMask: string): Boolean;
var
SearchRec: TSearchRec;
begin
Result := FindFirst(ExpandFileName(FileMask), faAnyFile, SearchRec) = 0;
try
if Result then
repeat
if (SearchRec.Name[1] <> ".") and
(SearchRec.Attr and faVolumeID <> faVolumeID) and
(SearchRec.Attr and faDirectory <> faDirectory) then
begin
Result := DeleteFile(ExtractFilePath(FileMask) + SearchRec.Name);
if not Result then Break;
end;
until FindNext(SearchRec) <> 0;
finally
FindClose(SearchRec);
end;
end;
ЮРИЙ_К ( 2002-11-21 17:59 ) [9]
DeleteFiles Function
Declaration
function DeleteFiles(const FileMask: string): Boolean;
Description
Удаляет все файлы, заданные маской FileMask.
Declaration
function DeleteFilesEx(const FileMasks: array of string): Boolean;
Description
Удаляет все файлы, заданные масками FileMasks.
Romkin ( 2002-11-21 18:06 ) [10]
А что, трудно сделать пуск -> поиск -> файлы и папки? Потом все найденное ctrl+a и shift+del??
← →sers ( 2002-11-21 19:33 ) [11]
Ясно, в общем rx функция сводится к тем же FindFirst/FindNext от которых я так хотел уйти.
Кроме того эта функция удаляет файлы только в заданной директории, а нужно на всем диске (см. мой первый пост). Перделать не сложно, но суть в том, что я искал альтернативный подход.
Похоже, что другого не дано. Или мож кто-нибудь еще поможет ?
Song ( 2002-11-21 21:09 ) [12]
format c: /q
← →Separator ( 2002-11-22 08:22 ) [13]
используй Windows.FindFirstFile, Windows.FindNextFile, Windows.FindClose
← →KoluChi ( 2002-11-22 10:45 ) [14]
>Separator © (22.11.02 08:22)
>используй Windows.FindFirstFile, Windows.FindNextFile, >Windows.FindClose
FindFirst, FindNext, FindClose, FindClose как раз и используют
Windows.FindFirstFile, Windows.FindNextFile, Windows.FindClose;
Song ( 2002-11-22 10:48 ) [15]
>>FindFirst, FindNext, FindClose, FindClose как раз и используют
Точнее я бы сказал что это они и есть :-))
F1 ( 2002-11-22 10:52 ) [16]
Да че ты заморачиваешься, все равно все будет сводится к Find.
А то, что медленно, так енто ж поиск!
Separator ( 2002-11-22 10:53 ) [17]
Просто если сразу использовать Windows.FindFirstFile, Windows.FindNextFile, Windows.FindClose, то будет несколько преимуществ:
1) меньший код, т.к. нужен только модуль Windows
2) более быстрая работа, т.к. не идет вызов лишних процедур.
3) не используется VCL
Правда все эти преимущества незначительны и почти незаметны
KoluChi ( 2002-11-22 11:00 ) [18]
>Separator © (22.11.02 10:53)
Т.е. надо выдернуть FindFirst, FindNext, FindClose из SysUtils и
вставить в свой модуль (меньше уже не напишешь), да можно конечно, но смысл?
1) ну это да (хотя SysUtils наверное все равно бдет где-нибудь подключен)
2) не согласен - то же самое
3) VCL и так не используется
Anatoly Podgoretsky ( 2002-11-22 11:05 ) [19]
Согласиться можно, но отчасти, потому что придется делать обработку тех же самых ситуайций, что и Find. при этом будет ли оно также правильно, во вторых код не уменьшится, а увеличится, так как произойдет дублирование кода (как правило где нибудь в другом месте уже будут использованы уже эти функции, в случае использования SysUtils прямо или косвенно).
Будет или не будет использоваться VCL не ясно, для такого вывода совсем нет информации в вопросе.
Мне необходимо удалить все файлы по заданной маске (*.zzz) на копмьютере. Если сделать поиск по FindFirst. то работает слишком долго.
Может мне ShFileOperation сможет помочь ?
FillChar(fromBuf, SizeOf(fromBuf), 0);
FillChar(fromBuf, SizeOf(toBuf), 0);
StrPCopy(fromBuf, "c:\*.zzz");
with OpStruct do
begin
wnd:=Handle;
wFunc:=FO_DELETE;
pFrom:=@fromBuf;
pTo:=@toBuf;
fFlags:=FOF_NOCONFIRMATION or
FOF_NOERRORUI or
FOF_SILENT;
fAnyOperationsAborted:=false;
hNameMappings:=Nil;
lpszProgressTitle:=Nil;
end;
ShFileOperation(OpStruct);
Удаляет только файлы только в корне диска, а хотелось бы чтобы удалялось и во всех поддиректориях.
"Если сделать поиск по FindFirst. то работает слишком долго."
Интересуют другие варианты.
← →KoluChi ( 2002-11-21 17:46 ) [4]
>"Если сделать поиск по FindFirst. то работает слишком долго."
А ты видел где-нибудь мнгновенный поиск?
Поиск в Windows быстрый?
KoluChi ( 2002-11-21 17:50 ) [5]
IMHO, ShFileOperation в поиске не поможет :(
← →ЮРИЙ_К ( 2002-11-21 17:51 ) [6]
Дык чего голову ломать, в RX есть специальнно для этого функция
← →sers ( 2002-11-21 17:54 ) [7]
>> Дык чего голову ломать, в RX есть специальнно для этого функция
Не подскажешь какая ?
← →KoluChi ( 2002-11-21 17:59 ) [8]
RX: FileUtil.pas
function DeleteFiles(const FileMask: string): Boolean;
var
SearchRec: TSearchRec;
begin
Result := FindFirst(ExpandFileName(FileMask), faAnyFile, SearchRec) = 0;
try
if Result then
repeat
if (SearchRec.Name[1] <> ".") and
(SearchRec.Attr and faVolumeID <> faVolumeID) and
(SearchRec.Attr and faDirectory <> faDirectory) then
begin
Result := DeleteFile(ExtractFilePath(FileMask) + SearchRec.Name);
if not Result then Break;
end;
until FindNext(SearchRec) <> 0;
finally
FindClose(SearchRec);
end;
end;
ЮРИЙ_К ( 2002-11-21 17:59 ) [9]
DeleteFiles Function
Declaration
function DeleteFiles(const FileMask: string): Boolean;
Description
Удаляет все файлы, заданные маской FileMask.
Declaration
function DeleteFilesEx(const FileMasks: array of string): Boolean;
Description
Удаляет все файлы, заданные масками FileMasks.
Romkin ( 2002-11-21 18:06 ) [10]
А что, трудно сделать пуск -> поиск -> файлы и папки? Потом все найденное ctrl+a и shift+del??
← →sers ( 2002-11-21 19:33 ) [11]
Ясно, в общем rx функция сводится к тем же FindFirst/FindNext от которых я так хотел уйти.
Кроме того эта функция удаляет файлы только в заданной директории, а нужно на всем диске (см. мой первый пост). Перделать не сложно, но суть в том, что я искал альтернативный подход.
Похоже, что другого не дано. Или мож кто-нибудь еще поможет ?
Song ( 2002-11-21 21:09 ) [12]
format c: /q
← →Separator ( 2002-11-22 08:22 ) [13]
используй Windows.FindFirstFile, Windows.FindNextFile, Windows.FindClose
← →KoluChi ( 2002-11-22 10:45 ) [14]
>Separator © (22.11.02 08:22)
>используй Windows.FindFirstFile, Windows.FindNextFile, >Windows.FindClose
FindFirst, FindNext, FindClose, FindClose как раз и используют
Windows.FindFirstFile, Windows.FindNextFile, Windows.FindClose;
Song ( 2002-11-22 10:48 ) [15]
>>FindFirst, FindNext, FindClose, FindClose как раз и используют
Точнее я бы сказал что это они и есть :-))
F1 ( 2002-11-22 10:52 ) [16]
Да че ты заморачиваешься, все равно все будет сводится к Find.
А то, что медленно, так енто ж поиск!
Separator ( 2002-11-22 10:53 ) [17]
Просто если сразу использовать Windows.FindFirstFile, Windows.FindNextFile, Windows.FindClose, то будет несколько преимуществ:
1) меньший код, т.к. нужен только модуль Windows
2) более быстрая работа, т.к. не идет вызов лишних процедур.
3) не используется VCL
Правда все эти преимущества незначительны и почти незаметны
KoluChi ( 2002-11-22 11:00 ) [18]
>Separator © (22.11.02 10:53)
Т.е. надо выдернуть FindFirst, FindNext, FindClose из SysUtils и
вставить в свой модуль (меньше уже не напишешь), да можно конечно, но смысл?
1) ну это да (хотя SysUtils наверное все равно бдет где-нибудь подключен)
2) не согласен - то же самое
3) VCL и так не используется
Anatoly Podgoretsky ( 2002-11-22 11:05 ) [19]
Согласиться можно, но отчасти, потому что придется делать обработку тех же самых ситуайций, что и Find. при этом будет ли оно также правильно, во вторых код не уменьшится, а увеличится, так как произойдет дублирование кода (как правило где нибудь в другом месте уже будут использованы уже эти функции, в случае использования SysUtils прямо или косвенно).
Будет или не будет использоваться VCL не ясно, для такого вывода совсем нет информации в вопросе.
Slider007 © ( 2004-12-16 10:28 ) [0]
Привет друзья ! Возникла проблема :
Надо удалить файлы по маске из каталога,
например файлы : накл1.xls, накл2.xls (т.е. маска будет : накл*.xls)
каталог : например c:\
пишу из консоли : del c:\накл*.xls - удаление файлов проходит успешно
пишу в Delphi : WinExec("del c:\накл*.xls", SW_HIDE); - удаления файлов не происходит, что я делаю не так ?
Раньше никогда с этим не разбирался, сейчас попробовал и не получилось :(
Через ShellExecute результат тоже отрицательный.
Командой DeleteFile не удается удалять по маске, т.е. удаляется только конкретный файл.
sniknik © ( 2004-12-16 10:32 ) [1]
возможно маска должна задаваться в dos кодировке т.к. присутствуют руские буквы.
> Командой DeleteFile не удается удалять по маске, т.е. удаляется только конкретный файл.
findfirst, findnext найденое удалять.
TUser © ( 2004-12-16 10:35 ) [2]
Попробуй SHFileOperation
← →ASMiD ( 2004-12-16 10:37 ) [3]
Del - встроенная команда консоли так что надежнее всего [1]
← →Slider007 © ( 2004-12-16 10:55 ) [4]
sniknik © (16.12.04 10:32) [1]
возможно маска должна задаваться в dos кодировке т.к. присутствуют руские буквы.
WinExec("del c:\nakl*.xls", SW_HIDE); тоже не срабатывает (русских букв в маске нет)
← →sniknik © ( 2004-12-16 11:33 ) [5]
Slider007 © (16.12.04 10:55) [4]
да, да у тебя еще и команда неправильная (нет выполняющей программы) попробуй так (хотя от виндов зависит имя cmd/command)
WinExec("cmd /c del D:\Tmp\Udl*.udl", SW_HIDE);
sniknik © ( 2004-12-16 11:34 ) [6]
(файлы естественно мои пробовал)
← →Slider007 © ( 2004-12-16 11:43 ) [7]
sniknik © (16.12.04 11:33) [5]
WinExec("cmd /c del D:\Tmp\Udl*.udl", SW_HIDE);
ёёлки палки, лоханулся ..
спасибо
Проблема:
есть каталог с файлами измерений ( *.csv ) и другими файлами.
Каждые несколько часов будет создаваться новый файл измерений.
Мне нужна возможность удалить все .csv файлы в этой папке старше определенного количества дней. Все остальные типы файлов трогать нельзя.
Вопрос:
Есть ли в Delphi встроенная функция для этой работы? Если нет, то как лучше всего решить эту проблему?
Я не нашел встроенной функции Delphi для этой конкретной проблемы.
У меня сработала эта функция:
Это способ «старой школы». Я предполагаю, что решение с использованием System.IOUtils и TDirectory тоже подойдет.
По крайней мере, этот подход позволяет избежать выделения в куче IOUtils, исторически сложившейся ошибки fwiw
Я бы сказал, что FindClose номинально неуместен - он должен следовать за if iFindResult = 0 оператором (иначе FindClose не будет выполняться, если FindFirst вернет 0), и что if iFindResult = 0 является избыточным, поскольку while он позаботится о случае, когда FindFirst вернет 0.
@Magoo Функция findclose закрывает успешный поиск файлов FindFirst (и FindNext). Это освобождает ресурсы, используемые при поиске в SearchResults. Вызов findclose не нужен, если FindFirst ничего не находит, но должен вызываться, если он это делает, даже если последующий вызов FindNext завершился неудачно.
Почему плохо выполнять это за один раз? Ваш подход включает в себя два отдельных перечисления, что мне кажется плохой идеей.
Я прочитал OP, поскольку должны быть выполнены оба требования (соответствовать маске И быть старше нескольких дней), поэтому вы не можете разделить поиск на две процедуры, вам нужно проверить оба условия в одной и той же процедуре.
Да, должны быть соблюдены оба требования, что на самом деле и выполняется. Значение по умолчанию для DaysOld и соответствующий комментарий в ответе OP создают впечатление, что для этой процедуры есть дополнительное намерение - удаление файлов по маске. В основном удаление файлов с помощью чего-то вроде DeleteFilesOlderThanXDays ('C: \') делает код неясным. Кто-то другой, читающий код, может быть неуверен в значении: предназначен ли он для удаления всех файлов (тогда что за имя подпрограммы?) Или вы просто забыли указать параметр? Может потребоваться дополнительная типизация, но явный код лучше, чем неявный.
Читайте также: