1

I want to copy only pdf files. I am using this method, if i know file name:

CopyFile(PChar(obPath.CaseTmpPath + '\' + currentCase.patientCase + '\Info_' + currentCase.patientCase + '.cxt'), PChar(obPath.ServerData + currentCase.patientCase + '\Info_' + currentCase.patientCase + '.cxt'), true);

this time, i dont know filenames. There are some files in directory like pdfs, jpegs. I just want to copy pdf files but how ?

Nevermore
  • 1,663
  • 7
  • 30
  • 56
  • 2
    Enumerate the files, and copy the ones with the desired extension. So you have the following tasks. 1. Learn how to enumerate files. 2. Learn how to get the file extension. 3. Learn how to compare strings. 4. Learn how to copy files. You can probably do of these and for those you don't already know, there are existing questions. – David Heffernan Apr 24 '18 at 12:56
  • @DavidHeffernan thank you, i thought may be there is a short way to do this. – Nevermore Apr 24 '18 at 12:59
  • [Here](https://stackoverflow.com/questions/5991040/how-to-search-different-file-types-using-findfirst) you can find some useful code – Fabrizio Apr 24 '18 at 13:09
  • 2
    I find it extremely hard to believe that you couldn't find any of this on Google. Unless you didn't even try? – Jerry Dodge Apr 24 '18 at 13:41
  • @JerryDodge i tried and i had known this way. I asked this question, because i thought maybe there was a short way like a function to do all this job. – Nevermore Apr 25 '18 at 08:55
  • If there were a shorter way, certainly Google would have turned up something about it. Or any other search engine =) – Jerry Dodge Apr 25 '18 at 16:39

1 Answers1

4

If you work with Windows only and you're not interested in code portability you can revert to win api:

uses
  ShellApi;

function MultiFileCopy(const ASource, ADest: string): Boolean;
var
  FO: TSHFileOpStruct;
begin
  FillChar(FO, SizeOf(FO), #0);
  FO.Wnd   := 0;
  FO.wFunc := FO_COPY;
  FO.pFrom := PChar(ASource + #0);
  FO.pTo   := PChar(ADest + #0);
  FO.fFlags := FOF_FILESONLY  or FOF_NOERRORUI or FOF_NOCONFIRMATION or FOF_SILENT;
  Result := (SHFileOperation(FO) = 0)and(not FO.fAnyOperationsAborted);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(BoolToStr(MultiFileCopy('C:\*.pdf', 'X:\'), True));
end;

The code above contains some trick to make method totally silent, please read documentation about SHFileOperation for flags and about SetErrorMode (as David noted SetErrorMode(SEM_FAILCRITICALERRORS) should be called only once during application initialization)

As Remy said in comment #0 are there because double null terminated strings are required.

BigBother
  • 367
  • 2
  • 9
  • 1
    The code messing with the error code is wrong and should be removed. – David Heffernan Apr 24 '18 at 13:48
  • @DavidHeffernan Sorry David, I read documentation again and it's seems correct to me, can you please tell me where it's wrong? – BigBother Apr 24 '18 at 14:09
  • You set this at process startup. – David Heffernan Apr 24 '18 at 16:16
  • @DavidHeffernan If you're talking about SetErrorMode I think the code was there to avoid error messages in case of unreachable source or dest disk (eg for drive A:). Now I can't verify but I'll be back soon with an answer. – BigBother Apr 24 '18 at 17:15
  • @DavidHeffernan Oh well yes, I've just read best practices notes about setting error mode just once. I'll edit post accordingly. Thanks a lot. – BigBother Apr 24 '18 at 17:20
  • 1
    "*Most #0 were there to solve some nasty error in the past, I'm not sure if they are useful, but surely don't harm.*" - not only do they not cause harm, they are REQUIRED, because those API parameters are defined as **double-null-terminated** strings that contain **null-separated** substrings. Read the API documentation. Delphi strings are already null-terminated, so adding `#0` makes them double-null-terminated – Remy Lebeau Apr 24 '18 at 18:32
  • @RemyLebeau thank you, old code, I didn't remember correctly – BigBother Apr 24 '18 at 18:48