如何在Rust中递归复制文件夹?

时间:2014-11-16 15:16:05

标签: rust

从我看到的in the documentation开始,没有开箱即用的解决方案。

5 个答案:

答案 0 :(得分:7)

use std::fs;
use std::path::{Path, PathBuf};

pub fn copy<U: AsRef<Path>, V: AsRef<Path>>(from: U, to: V) -> Result<(), std::io::Error> {
    let mut stack = Vec::new();
    stack.push(PathBuf::from(from.as_ref()));

    let output_root = PathBuf::from(to.as_ref());
    let input_root = PathBuf::from(from.as_ref()).components().count();

    while let Some(working_path) = stack.pop() {
        println!("process: {:?}", &working_path);

        // Generate a relative path
        let src: PathBuf = working_path.components().skip(input_root).collect();

        // Create a destination if missing
        let dest = if src.components().count() == 0 {
            output_root.clone()
        } else {
            output_root.join(&src)
        };
        if fs::metadata(&dest).is_err() {
            println!(" mkdir: {:?}", dest);
            fs::create_dir_all(&dest)?;
        }

        for entry in fs::read_dir(working_path)? {
            let entry = entry?;
            let path = entry.path();
            if path.is_dir() {
                stack.push(path);
            } else {
                match path.file_name() {
                    Some(filename) => {
                        let dest_path = dest.join(filename);
                        println!("  copy: {:?} -> {:?}", &path, &dest_path);
                        fs::copy(&path, &dest_path)?;
                    }
                    None => {
                        println!("failed: {:?}", path);
                    }
                }
            }
        }
    }

    Ok(())
}

其他答案实际上并没有显示该如何做,只是说您可能如何做;这是一个具体的例子。

如其他答案所述,相关的API为fs::create_dir_allfs::copyfs::metadata

没有为此提供“所有功能”的标准库API。

答案 1 :(得分:4)

您可以使用我撰写的fs_extra crate。此包会扩展标准库std::fsstd::io模块。

它可以(除其他外):

  • 复制文件(可选择包含有关进度的信息)。
  • 递归复制目录(可选择包含有关进度的信息)。

答案 2 :(得分:3)

您可以使用std::io::fs::walk_dir递归遍历目录结构,这会产生Result中的迭代器,并且对于每个Path,使用{{检查它是否是一个文件3}} PathExtensions扩展特性提供的方法。如果是,则使用is_file()实际复制文件。

答案 3 :(得分:0)

fs_extra根本不适合我。它还具有令人困惑的选项,并且总体质量令人怀疑(例如,他们认为64000字节为64 kB)。

无论如何,可行的替代方法是copy_dir,它包含一个执行此操作的函数,没有选项。它不会覆盖现有目录,但是您可以修改代码以使其非常容易。

答案 4 :(得分:0)

我找到的最简单的代码有效:

use std::{io, fs};

fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
    fs::create_dir_all(&dst)?;
    for entry in fs::read_dir(src)? {
        let entry = entry?;
        let ty = entry.file_type()?;
        if ty.is_dir() {
            copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?;
        } else {
            fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?;
        }
    }
    Ok(())
}