【问题标题】:Lazarus & Free Pascal - How to recursively copy a source directory of files to another directory?Lazarus & Free Pascal - 如何递归地将文件的源目录复制到另一个目录?
【发布时间】:2012-03-05 22:00:24
【问题描述】:

我需要向我的 Lazarus & Free Pascal GUI 程序添加一些功能 - 我还需要它来将文件从用户选择的目录复制到另一个目录。我有源目录的“选择源”TSelectDirectoryDialog 按钮 onclick 事件和目标目录的“选择目标”TSelectDirectoryDialog 按钮 onclick 事件。我有第三个按钮来进行从源到目标的复制。

到目前为止,我已经找到了复制文件和原始日期属性的 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 Thread

非常感谢

泰德

【问题讨论】:

  • 在 Python 中,例如,就这么简单: DestinationDirectory = os.path.join(os.getcwd(), 'DestDirPath') shutil.copytree(SourceDirectory, DestDirPath) (@987654322 @)
  • 你打算只使用 Windows 平台还是需要它独立于平台?我问是因为 Windows Shell 可能会使用我猜的一个功能来完成它(同样的功能很可能有,例如 Linux)。
  • 嗨,TLama。我刚刚注意到你的评论。抱歉耽搁了。我刚刚在下面发布了我自己的答案,所以请不要在上面花费任何时间。但是要回答您的问题,它必须独立于操作系统,因为它是跨平台的。我还没有更彻底地测试我的答案,但这应该在 Linux(经过测试)和 Windows(未经测试)上都能正常工作。泰德

标签: freepascal lazarus file-copying


【解决方案1】:

我非常高兴和自豪,并且第一次回答我自己的问题!我把整个事情都归结为基础,不再阅读其他人的更复杂的例子(因为他们只是让我感到困惑)。我坚持Lazarus FileUtils Ref 列出的基本程序,并想出了这个,它有效。我需要构建一些错误检查和东西,但是我现在拥有的是获取源目录的代码,在目标目录中重建它,然后将文件从原始目录复制到目标,使用完全免费的 Pascal 代码并且没有操作系统特定的语法。为了他人的利益,粘贴在下面。请添加任何建设性的 cmets 以使其更好、更快、更高效。谢谢。

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;       

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-07
    • 2010-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-18
    • 2012-02-15
    相关资源
    最近更新 更多