Sim*_*han 20
我发现有效的最简单的代码:
use std::path::Path;
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(())
}
Run Code Online (Sandbox Code Playgroud)
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(())
}
Run Code Online (Sandbox Code Playgroud)
其他答案实际上并没有说明如何去做,他们只是说你可以怎样做;这是一个具体的例子。
正如其他答案中所讨论的,相关的 API 是fs::create_dir_all、fs::copy和fs::metadata。
对此没有“多合一”标准库 API。
您可以使用 递归地遍历目录结构std::fs::walk_dir,这会在 a 中生成一个迭代器Result,并且对于每个,使用扩展特征提供的方法Path检查它是否是一个文件。如果是,则用于实际复制该文件。is_file()PathExtensionsstd::io::fs::copy
您可以使用我编写的fs_extra板条箱。此板条箱在标准库std::fs和std::io模块上扩展。
它可以(除其他外):