Created
August 14, 2022 19:07
-
-
Save AyAyEm/50dad1580c8fad62978950960b6d01f6 to your computer and use it in GitHub Desktop.
Non recursive async directory copy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use std::{collections::VecDeque, path::PathBuf}; | |
| use tokio::io; | |
| #[derive(Debug, Clone, Copy)] | |
| pub struct CopyOptions { | |
| pub overwrite: bool, | |
| } | |
| impl Default for CopyOptions { | |
| fn default() -> Self { | |
| Self { overwrite: false } | |
| } | |
| } | |
| pub async fn dir<F, T>(from: F, to: T, options: &CopyOptions) -> io::Result<()> | |
| where | |
| F: Into<PathBuf>, | |
| T: Into<PathBuf>, | |
| { | |
| let from: PathBuf = from.into(); | |
| let to: PathBuf = to.into(); | |
| let component_count = from.components().count(); | |
| let to_path = |from_path: &PathBuf| { | |
| let from_path = from_path | |
| .components() | |
| .skip(component_count) | |
| .collect::<PathBuf>(); | |
| to.join(from_path) | |
| }; | |
| let mut futures = vec![]; | |
| let mut directories = VecDeque::from([from]); | |
| while let Some(dir) = directories.pop_front() { | |
| let mut read_dir = tokio::fs::read_dir(dir).await?; | |
| while let Ok(Some(entry)) = read_dir.next_entry().await { | |
| let file_type = entry.file_type().await?; | |
| let path = entry.path(); | |
| if file_type.is_dir() { | |
| directories.push_back(path); | |
| } else { | |
| futures.push(async { | |
| let copy_path = to_path(&path); | |
| if let Some(parent) = copy_path.parent() { | |
| match tokio::fs::create_dir_all(parent).await { | |
| Err(err) => match err.kind() { | |
| io::ErrorKind::AlreadyExists => Ok(()), | |
| _ => Err(err), | |
| }, | |
| _ => Ok(()), | |
| }?; | |
| } | |
| match (copy_path.try_exists(), options.overwrite) { | |
| (Ok(false), _) | (Ok(true), true) => { | |
| tokio::fs::copy(path, copy_path).await | |
| } | |
| _ => Ok(0), | |
| } | |
| }); | |
| } | |
| } | |
| } | |
| futures_util::future::try_join_all(futures).await?; | |
| Ok(()) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment