Crate recv_dir

source ·
Expand description

§recv-dir

Simple recursive directory traversal.

§Usage

recv-dir implements a simple directory traversal, which supports selective directory visit.

Since it is a simple iterator, you can use regular iterator functions like filter and map to ignore individual files or directories, but it does not prevent them from being visited.

To ignore directories from being visited, you will need to use a filtered iterator, like the examples below.

§Example

§Visit all directories

use recv_dir::RecursiveDirIterator;
let dir = RecursiveDirIterator::from_root("test_dir").unwrap();

for entry in dir {
   println!("{:?}", entry);
}
use std::path::Path;
use recv_dir::RecursiveDirIterator;
let dir = RecursiveDirIterator::with_closure_filter("test_dir", |dir: &Path| !dir.is_symlink()).unwrap();

for entry in dir {
   println!("{:?}", entry);
}

§Control depth

Visits only the files in test_dir:

use std::path::{Path, PathBuf};
use recv_dir::RecursiveDirIterator;
let root = PathBuf::from("test_dir");
let ancestors = root.ancestors().count();
let dir = RecursiveDirIterator::with_closure_filter(root, |dir: &Path| dir.ancestors().count() - ancestors <= 1).unwrap();

for entry in dir {
   println!("{:?}", entry);
}

Visits the files in test_dir and in first-level sub directories:

use std::path::{Path, PathBuf};
use recv_dir::RecursiveDirIterator;
let root = PathBuf::from("test_dir");
let ancestors = root.ancestors().count();
let dir = RecursiveDirIterator::with_closure_filter(root, |dir: &Path| dir.ancestors().count() - ancestors <= 2).unwrap();

for entry in dir {
   println!("{:?}", entry);
}

You can also compose the filters:

use std::num::NonZeroUsize;
use std::path::{Path, PathBuf};
use recv_dir::{Filter, MaxDepth, NoSymlink, RecursiveDirIterator};
let root = PathBuf::from("test_dir");
let dir = RecursiveDirIterator::with_filter(&root, NoSymlink.and(MaxDepth::new(&root, NonZeroUsize::new(2).unwrap()))).unwrap();

for entry in dir {
   println!("{:?}", entry);
}

§Order

There is no guarantee on the order of the traversal, it may be OS-dependent, File System-dependent or completely arbitrary.

But it does not means that there is no guarantees at all, this crate relies on std::fs::read_dir, and it is expected that, at least, the same directory is not visited twice. Although it is extremely unlikely to happen, it is still possible, mainly when considering symlink recursions.

Some filesystems has a very consistent order of traversal, and others don’t, directories are commonly stored in B-trees (or B+ trees), and commonly respects their order, but it may vary.

recv-dir does not guarantee that either directories or files are visited first, but it is guaranteed that they are visited at some point if accessible, even if directories were already visited.

§Failures

Walking the directory tree may fail and at the moment, recv-dir will only fail if the base directory cannot be visited, but it will silently ignore the sub directories that are not accessible or fails to open.

§Recursion

recv-dir is stack-based, which means that it will never crash because of recursion limits, however, recursion limits are good to prevent the tree-walk going too deep (and they are also the worse way to handle this and have an extremely negative performance impact).

Because it never crashes, if you do visit symlinks (which is the default), you can end up in an infinite symlink recursion, which will cause high-cpu usage and can also cause the stack to grow until it consumes all the available memory, which in a good scenario, means that the program will crash, but in a bad scenario (and if the stack do not grow) it will just run indefinitely.

To avoid this, you can either configure a maximum depth or never visit symlinks, since, at the moment, recv-dir does not provide a protection against infinite symlink recursion.

§Experiment

This project is part of the Kores/rust-experiments.

Structs§

Traits§

Functions§