Lazarus & Free Pascal - Как рекурсивно скопировать исходный каталог файлов в другой каталог? - PullRequest
1 голос
/ 14 февраля 2012

Мне нужно добавить некоторые функциональные возможности в мою программу Lazarus & Free Pascal GUI - мне нужно также копировать файлы из выбранного пользователем каталога в другой каталог.У меня есть событие onclick кнопки «Выбрать источник» TSelectDirectoryDialog для исходного каталога и событие onclick кнопки «Выбрать место назначения» TSelectDirectoryDialog для каталога назначения.У меня есть третья кнопка, чтобы сделать копирование из источника в место назначения.

До сих пор я обнаружил CopyFile, который копирует файлы и исходные атрибуты даты, но он не воссоздает структуру подкаталогов каких-либо подкаталогов из выбранного пользователем исходного каталога.По сути, я пытаюсь скопировать исходный каталог в новый каталог в другом месте.

Я получил это далеко:

Public Vars :
DestDir, SourceDir : string
...
FS := TFileSearcher.Create;
FS.OnFileFound := @CopyTheFile;  // CopyTheFile is my own procedure 
FS.Search(SourceDir, '*', True);   
...

procedure TForm1.CopyTheFile(FileIterator: TFileIterator);
var
  DestinationName: String;
begin
  DestinationName := IncludeTrailingPathDelimiter(DestDir) + ExtractFileName(FileIterator.FileName);
  if not FileUtil.CopyFile(FileIterator.FileName, DestinationName, true) then
    ShowMessage(FileIterator.FileName + ' failed to copy');
end;        

Может кто-нибудь помочь мне с тем, как кодировать при копировании подкаталогов и их файлов?Я также задавал вопрос на форуме Lazarus здесь: Тема Lazarus

Большое спасибо

Тед

1 Ответ

1 голос
/ 22 февраля 2012

Я ОЧЕНЬ СЧАСТЛИВ и ИЩУ, и впервые даю ответ на свой вопрос!Я вернул все это к основам и перестал читать более сложные примеры других людей (потому что они просто смутили меня).Я придерживался основных процедур, перечисленных в Lazarus FileUtils Ref , и придумал, что работает.Мне нужно встроить некоторую проверку ошибок и прочее, но теперь у меня есть код, который берет исходный каталог, перестраивает его в целевой каталог, а затем копирует файлы из исходного каталога в целевой, используя полностью свободный код Pascal и неОС специфический синтаксис.Вставлено ниже для пользы других.Пожалуйста, добавьте любые конструктивные комментарии, чтобы сделать его лучше, быстрее, эффективнее.Благодарю.

procedure TForm1.Button3Click(Sender: TObject);
begin
  ProcessDir(SourceDir);
end;

procedure TForm1.ProcessDir(const SourceDirName: string);

var
  NoOfFilesFoundInSourceDir, i, NoOfFilesCopiedOK : integer;
  FilesFoundToCopy : TStringList;
  SourceDirectoryAndFileName, SubDirStructure, FinalisedDestDir, FinalisedFileName : string;

begin
  Memo1.Lines.Clear;
  SubDirStructure := '';
  FinalisedDestDir := '';
  NoOfFilesFoundInSourceDir := 0;
  NoOfFilesCopiedOK := 0;

  // Ensures the selected source directory is set as the directory to be searched
  // and then fina all the files and directories within, storing as a StringList.

  SetCurrentDir(SourceDirName);
  FilesFoundToCopy := FindAllFiles(SourceDirName, '*', True);
  NoOfFilesFoundInSourceDir := FilesFoundToCopy.Count;

  try
    for i := 0 to FilesFoundToCopy.Count -1 do
      begin
        Memo1.Lines.Add('File Index : '+IntToStr(i)+' File Name: '+FilesFoundToCopy.Strings[i]);
        SourceDirectoryAndFileName := ChompPathDelim(CleanAndExpandDirectory(FilesFoundToCopy.Strings[i]));

    // Determine the source sub-dir structure, from selected dir downwards

    SubDirStructure := IncludeTrailingPathDelimiter(ExtractFileDir(SourceDirectoryAndFileName));

    // Now concatenate the original sub directory to the destination directory and form the total path, inc filename
    // Note : Only directories containing files will be recreated in destination. Empty dirs are skipped.
    // Zero byte files are copied, though, even if the directory contains just one zero byte file.

    FinalisedDestDir := DestDir+SubDirStructure;
    FinalisedFileName := ExtractFileName(FilesFoundToCopy.Strings[i]);

    // Now create the destination directory structure, if it is not yet created. If it exists, just copy the file.

    if not DirPathExists(FinalisedDestDir) then
      begin
        if not ForceDirectories(FinalisedDestDir) then
          begin
            ShowMessage(FinalisedDestDir+' cannot be created.');
          end;
      end;

    // Now copy the files to the destination dir

    if not FileUtil.CopyFile(SourceDirectoryAndFileName, FinalisedDestDir+FinalisedFileName, true) then
      begin
        ShowMessage('Failed to copy file : ' + SourceDirectoryAndFileName)
      end
    else
    NoOfFilesCopiedOK := NoOfFilesCopiedOK + 1;
  end;
  finally
    FilesFoundToCopy.free;
  end;
  ShowMessage('Total files copied OK : ' + IntToStr(NoOfFilesCopiedOK));
end;       
...