Search code examples
delphifile-copyingmovefileex

Copy everything from a source directory to a new directory Delphi EX7


My end goal is to copy all the relevant files from one folder to another. So e.g. we have C:\Users\Tool\Desktop\test\oldStuff. In the folder oldStuff we have more folders as well as some mp3,mp4 and txt files.

Now what I would like to do is copy all the mp4 files that are smaller than a GB to C:\Users\Tool\Desktop\test\New_Stuff_Less_than_a_Gig, and the .mp4 files that are bigger than a GB to C:\Users\Tool\Desktop\test\New_STuff_Bigger_than_a_Gig.

I though is this would be pretty easy but I was wrong. So far have this, didn't worry about file type for now so just made it *.*

 procedure TForm4.Button1Click(Sender: TObject);
 var
   f: TSearchRec;
   Dir: string;
 begin
    if not SelectDirectory(Dir,widestring(Dir),Dir) then   Exit;
    FileMode:=0;
    if FindFirst(Dir+'\*.*',faAnyFile,f) = 0 then
    repeat
         try
          if (f.Attr and faDirectory ) < $00000008 then
          CopyFile(PChar(Dir+'\'+f.Name),PChar
 ('C:\Users\Tool\Desktop\test\new\'+f.Name),false);
         except
          on e: exception do
            ShowMessage(E.Message);
         end;
    until findNext(f) <> 0
 end;

which will copy anything in the folder that is selected but it doesn't copy anything from the folders within the selected folder. E.g. if we have C:\Users\Tool\Desktop\test\oldStuff\movie.mp4 it will copy the Movie.mp4 file but if we have C:\Users\Tool\Desktop\test\oldStuff\movies\Movie.mp4 it won't copy the Movie.mp4 file. I though I could just do something like this

CopyFile.size < 1000 (PChar('C:\Users\Tool\Desktop\test\oldStuff\*.*'+f.Name),
                   PChar('C:\Users\Tool\Desktop\test\new_Stuff\'+f.Name),false)

or even just

CopyFile (PChar('C:\Users\Tool\Desktop\test\old\*.*'+f.Name),
                   PChar('C:\Users\Tool\Desktop\test\new\'+f.Name),false);

but it didn't copy anything.


Solution

  • Here's an example (done in XE7) that will do what you want. You'll need to modify it to suit your needs, obviously; it has hard-coded path information and file mask (*.png) and uses a constant to decide whether the file is large or small.

    It's based on this sample directory tree:

    D:\TempFiles
      |--\Test
      |-----\A
      |-----\B
      |--------\SubB   
      |-----\NewFiles
      |-------\Large
      L-------\Small
    

    It finds all of the .png files in D:\TempFiles\Test and it's subfolders, and copies the ones equal to or larger than 10KB to D:\TempFiles\NewFiles\Large and the ones smaller than 10KB to D:\TempFiles\NewFiles\Small.

    You'll need to add IOUtils and Types to your implementation uses clause.

    procedure TForm1.Button1Click(Sender: TObject);
    var
      aLargeFiles: TStringDynArray;
      aSmallFiles: TStringDynArray;
    const
      LargeSize = 10 * 1024;
      SourcePath = 'D:\TempFiles\Test\';
    begin
      aLargeFiles := TDirectory.GetFiles(SourcePath, '*.png',
                       TSearchOption.soAllDirectories,
                       function (const Path: string; const SR: TSearchRec): Boolean
                       begin
                         Result := (SR.Size >= LargeSize);
                       end);
      aSmallFiles := TDirectory.GetFiles(SourcePath, '*.png',
                       TSearchOption.soAllDirectories,
                       function(const Path: string; const SR: TSearchRec):Boolean
                       begin
                         Result := (SR.Size < LargeSize);
                       end);
      CopyFilesToPath(aLargeFiles, 'D:\TempFiles\NewFiles\Large\');
      CopyFilesToPath(aSmallFiles, 'D:\TempFiles\NewFiles\Small\');
    end;
    
    procedure TForm1.CopyFilesToPath(aFiles: array of string; DestPath: string);
    var
      InFile, OutFile: string;
    begin
      for InFile in aFiles do
      begin
        OutFile := TPath.Combine( DestPath, TPath.GetFileName( InFile ) );
        TFile.Copy( InFile, OutFile, True);
      end;
    end;