fs-more 0.5.1

Convenient file and directory operations with progress reporting built on top of std::fs.
Documentation

fs-more

Crates.io Version Minimum Supported Rust Version is 1.77.0 License Documentation

Convenient file and directory operations built on top of std::fs with improved error handling. Includes copying and moving files or directories with progress reporting.

Main features

  • copying and moving files or directories with:
    • in-depth configuration options (existing destination file behaviour, IO buffering settings, copying depth, etc.), and
    • progress reporting, if needed,
  • scan directories (with options such as scan depth and symlink behaviour), and
  • calculate file or directory sizes.

Usage

To add fs-more into your project, specify it as a dependency in your Cargo.toml file:

fs-more = "0.5.1"

Examples

Copying a file and getting updates on the progress:

use std::path::Path;

use fs_more::file::ExistingFileBehaviour;
use fs_more::file::FileCopyWithProgressOptions;
use fs_more::file::FileCopyFinished;


let source_path = Path::new("./source-file.txt");
let destination_path = Path::new("./destination-file.txt");

let finished_copy = fs_more::file::copy_file_with_progress(
    source_path,
    destination_path,
    FileCopyWithProgressOptions {
        existing_destination_file_behaviour: ExistingFileBehaviour::Abort,
        ..Default::default()
    },
    |progress| {
        let percent_copied =
            (progress.bytes_finished as f64) 
            / (progress.bytes_total as f64 * 100.0);

        println!("Copied {:.2}% of the file!", percent_copied);
    }
).unwrap();

match finished_copy {
    FileCopyFinished::Created { bytes_copied } => {
        println!("Copied {bytes_copied} bytes into a fresh file!");
    }
    FileCopyFinished::Overwritten { bytes_copied } => {
        println!("Copied {bytes_copied} bytes over an existing file!");
    }
    // ... (see documentation) ...
    _ => {}
};

Moving a directory and getting updates on the progress:

use std::path::Path;
use fs_more::directory::DirectoryMoveWithProgressOptions;
use fs_more::directory::DestinationDirectoryRule;


let source_path = Path::new("./source-directory");
let destination_path = Path::new("./destination-directory");

let moved = fs_more::directory::move_directory_with_progress(
    source_path,
    destination_path,
    DirectoryMoveWithProgressOptions {
        destination_directory_rule: DestinationDirectoryRule::AllowEmpty,
        ..Default::default()
    },
    |progress| {
        let percent_moved =
            (progress.bytes_finished as f64) / (progress.bytes_total as f64)
            * 100.0;
        println!(
            "Moved {:.2}% of the directory ({} files and {} directories so far).",
            percent_moved,
            progress.files_moved,
            progress.directories_created
        );
    }
).unwrap();

println!(
    "Moved {} bytes ({} files, {} directories)! Underlying strategy: {:?}.",
    moved.total_bytes_moved,
    moved.files_moved,
    moved.directories_moved,
    moved.strategy_used
);

Feature flags

The following feature flags are available:

  • dunce (enabled by default): enables the optional dunce support: This automatically strips Windows' UNC paths if they can be represented using the usual type of path (e.g. \\?\C:\foo -> C:\foo). This is used both internally and in e.g. DirectoryScan's file and directory paths. This feature flag is enabled by default and recommended because because path canonicalization very commonly returns UNC paths. This crate only has an effect when compiling for Windows targets.
  • fs-err (disabled by default): enables fs-err support, which means more helpful underlying IO error messages (though fs-more already provides many on its own).

Project status

fs-more does lack some thorough battle-testing; as such, use it with care. The majority of common features are present. For now, we plan on keeping the version below stable (1.0.0) to imply that this crate hasn't gone through a lot.

Quite a number of unit-, doc- and integration tests have been written. They cover a wide array of the base functionality, but fringe cases might not be covered yet — contributions are welcome. The quite comprehensive test harness is available in subcrates/test-harness.

How to contribute

Found a bug or just want to improve fs-more by developing new features or writing tests? Awesome! Start by going over the contribution guide: CONTRIBUTING.md.

Contributions for the ideas below are most welcome!

Some of these ideas and/or missing features are simpler, some are more of a long shot. However, note that even though they are stated below, they probably haven't been thought out deeply enough. If you decide to contribute, it would probably be best to first open an issue, so various approaches can be discussed before something is developed.

  • Cross-platform: allow copying file and directory permissions.

    This partially already exists in some functions, but it inconsistent across the API. The reason is that std::fs::copy already copies permission bits, but we don't use that in several places, since copying with progress reporting makes using std::fs::copy impossible. Ideally, we should expose a new option through the existing *Options structs and make this consistent.

    I think this should be reasonably simple to do, but it might take some thinking about edge cases and implementing some platform-specifics (i.e. on Windows, we probably want to copy the hidden file flag, etc).

  • On Unix: allow copying file and directory owners and groups.

    Depending on how deep the implementation rabbit-hole goes, perhaps using file-owner or nix could suffice? Perhaps we should feature-gate these kinds of things so the average user doesn't need to pull in so many dependencies?

  • Cross-platform: allow copying creation/access/modification time of files and directories (across the entire API). This could also include various other metadata.

    Ideally, this should be highly configurable through the existing *Options structs. This might take some more work though due to various platform differences (see: Unix, Linux, Windows).

    It might be more feasible to simply delegate this to some existing crate, i.e. filetime (but this one covers only timestamps). Perhaps we should start with just creation/access/modification timestamps and expand later?

  • On Windows: allow copying the ACL of files and directories.

    This seems like a long shot and would need some concrete use cases before proceeding. Maybe windows-acl could help? If this feature is to be developed, I think we should not expose any underlying ACL API and allow purely for mirroring it when copying or moving. This should definitely be under a feature flag.


License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.